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 #include "sim-main.h" 15 #include "sim-fpu.h" 16 17 /* SF mode support */ 18 19 static SF 20 addsf (CGEN_FPU* fpu, SF x, SF y) 21 { 22 sim_fpu op1; 23 sim_fpu op2; 24 sim_fpu ans; 25 unsigned32 res; 26 sim_fpu_status status; 27 28 sim_fpu_32to (&op1, x); 29 sim_fpu_32to (&op2, y); 30 status = sim_fpu_add (&ans, &op1, &op2); 31 if (status != 0) 32 (*fpu->ops->error) (fpu, status); 33 sim_fpu_to32 (&res, &ans); 34 35 return res; 36 } 37 38 static SF 39 subsf (CGEN_FPU* fpu, SF x, SF y) 40 { 41 sim_fpu op1; 42 sim_fpu op2; 43 sim_fpu ans; 44 unsigned32 res; 45 sim_fpu_status status; 46 47 sim_fpu_32to (&op1, x); 48 sim_fpu_32to (&op2, y); 49 status = sim_fpu_sub (&ans, &op1, &op2); 50 if (status != 0) 51 (*fpu->ops->error) (fpu, status); 52 sim_fpu_to32 (&res, &ans); 53 54 return res; 55 } 56 57 static SF 58 mulsf (CGEN_FPU* fpu, SF x, SF y) 59 { 60 sim_fpu op1; 61 sim_fpu op2; 62 sim_fpu ans; 63 unsigned32 res; 64 sim_fpu_status status; 65 66 sim_fpu_32to (&op1, x); 67 sim_fpu_32to (&op2, y); 68 status = sim_fpu_mul (&ans, &op1, &op2); 69 if (status != 0) 70 (*fpu->ops->error) (fpu, status); 71 sim_fpu_to32 (&res, &ans); 72 73 return res; 74 } 75 76 static SF 77 divsf (CGEN_FPU* fpu, SF x, SF y) 78 { 79 sim_fpu op1; 80 sim_fpu op2; 81 sim_fpu ans; 82 unsigned32 res; 83 sim_fpu_status status; 84 85 sim_fpu_32to (&op1, x); 86 sim_fpu_32to (&op2, y); 87 status = sim_fpu_div (&ans, &op1, &op2); 88 if (status != 0) 89 (*fpu->ops->error) (fpu, status); 90 sim_fpu_to32 (&res, &ans); 91 92 return res; 93 } 94 95 static SF 96 negsf (CGEN_FPU* fpu, SF x) 97 { 98 sim_fpu op1; 99 sim_fpu ans; 100 unsigned32 res; 101 sim_fpu_status status; 102 103 sim_fpu_32to (&op1, x); 104 status = sim_fpu_neg (&ans, &op1); 105 if (status != 0) 106 (*fpu->ops->error) (fpu, status); 107 sim_fpu_to32 (&res, &ans); 108 109 return res; 110 } 111 112 static SF 113 abssf (CGEN_FPU* fpu, SF x) 114 { 115 sim_fpu op1; 116 sim_fpu ans; 117 unsigned32 res; 118 sim_fpu_status status; 119 120 sim_fpu_32to (&op1, x); 121 status = sim_fpu_abs (&ans, &op1); 122 if (status != 0) 123 (*fpu->ops->error) (fpu, status); 124 sim_fpu_to32 (&res, &ans); 125 126 return res; 127 } 128 129 static SF 130 sqrtsf (CGEN_FPU* fpu, SF x) 131 { 132 sim_fpu op1; 133 sim_fpu ans; 134 unsigned32 res; 135 sim_fpu_status status; 136 137 sim_fpu_32to (&op1, x); 138 status = sim_fpu_sqrt (&ans, &op1); 139 if (status != 0) 140 (*fpu->ops->error) (fpu, status); 141 sim_fpu_to32 (&res, &ans); 142 143 return res; 144 } 145 146 static SF 147 invsf (CGEN_FPU* fpu, SF x) 148 { 149 sim_fpu op1; 150 sim_fpu ans; 151 unsigned32 res; 152 sim_fpu_status status; 153 154 sim_fpu_32to (&op1, x); 155 status = sim_fpu_inv (&ans, &op1); 156 if (status != 0) 157 (*fpu->ops->error) (fpu, status); 158 sim_fpu_to32 (&res, &ans); 159 160 return res; 161 } 162 163 static SF 164 minsf (CGEN_FPU* fpu, SF x, SF y) 165 { 166 sim_fpu op1; 167 sim_fpu op2; 168 sim_fpu ans; 169 unsigned32 res; 170 sim_fpu_status status; 171 172 sim_fpu_32to (&op1, x); 173 sim_fpu_32to (&op2, y); 174 status = sim_fpu_min (&ans, &op1, &op2); 175 if (status != 0) 176 (*fpu->ops->error) (fpu, status); 177 sim_fpu_to32 (&res, &ans); 178 179 return res; 180 } 181 182 static SF 183 maxsf (CGEN_FPU* fpu, SF x, SF y) 184 { 185 sim_fpu op1; 186 sim_fpu op2; 187 sim_fpu ans; 188 unsigned32 res; 189 sim_fpu_status status; 190 191 sim_fpu_32to (&op1, x); 192 sim_fpu_32to (&op2, y); 193 status = sim_fpu_max (&ans, &op1, &op2); 194 if (status != 0) 195 (*fpu->ops->error) (fpu, status); 196 sim_fpu_to32 (&res, &ans); 197 198 return res; 199 } 200 201 static CGEN_FP_CMP 202 cmpsf (CGEN_FPU* fpu, SF x, SF y) 203 { 204 sim_fpu op1; 205 sim_fpu op2; 206 207 sim_fpu_32to (&op1, x); 208 sim_fpu_32to (&op2, y); 209 210 if (sim_fpu_is_nan (&op1) 211 || sim_fpu_is_nan (&op2)) 212 return FP_CMP_NAN; 213 214 if (x < y) 215 return FP_CMP_LT; 216 if (x > y) 217 return FP_CMP_GT; 218 return FP_CMP_EQ; 219 } 220 221 static int 222 eqsf (CGEN_FPU* fpu, SF x, SF y) 223 { 224 sim_fpu op1; 225 sim_fpu op2; 226 227 sim_fpu_32to (&op1, x); 228 sim_fpu_32to (&op2, y); 229 return sim_fpu_is_eq (&op1, &op2); 230 } 231 232 static int 233 nesf (CGEN_FPU* fpu, SF x, SF y) 234 { 235 sim_fpu op1; 236 sim_fpu op2; 237 238 sim_fpu_32to (&op1, x); 239 sim_fpu_32to (&op2, y); 240 return sim_fpu_is_ne (&op1, &op2); 241 } 242 243 static int 244 ltsf (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_lt (&op1, &op2); 252 } 253 254 static int 255 lesf (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_le (&op1, &op2); 263 } 264 265 static int 266 gtsf (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_gt (&op1, &op2); 274 } 275 276 static int 277 gesf (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_ge (&op1, &op2); 285 } 286 287 static DF 288 fextsfdf (CGEN_FPU* fpu, int how UNUSED, SF x) 289 { 290 sim_fpu op1; 291 unsigned64 res; 292 293 sim_fpu_32to (&op1, x); 294 sim_fpu_to64 (&res, &op1); 295 296 return res; 297 } 298 299 static SF 300 ftruncdfsf (CGEN_FPU* fpu, int how UNUSED, DF x) 301 { 302 sim_fpu op1; 303 unsigned32 res; 304 305 sim_fpu_64to (&op1, x); 306 sim_fpu_to32 (&res, &op1); 307 308 return res; 309 } 310 311 static SF 312 floatsisf (CGEN_FPU* fpu, int how UNUSED, SI x) 313 { 314 sim_fpu ans; 315 unsigned32 res; 316 317 sim_fpu_i32to (&ans, x, sim_fpu_round_near); 318 sim_fpu_to32 (&res, &ans); 319 return res; 320 } 321 322 static DF 323 floatsidf (CGEN_FPU* fpu, int how UNUSED, SI x) 324 { 325 sim_fpu ans; 326 unsigned64 res; 327 328 sim_fpu_i32to (&ans, x, sim_fpu_round_near); 329 sim_fpu_to64 (&res, &ans); 330 return res; 331 } 332 333 static SF 334 ufloatsisf (CGEN_FPU* fpu, int how UNUSED, USI x) 335 { 336 sim_fpu ans; 337 unsigned32 res; 338 339 sim_fpu_u32to (&ans, x, sim_fpu_round_near); 340 sim_fpu_to32 (&res, &ans); 341 return res; 342 } 343 344 static SI 345 fixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x) 346 { 347 sim_fpu op1; 348 unsigned32 res; 349 350 sim_fpu_32to (&op1, x); 351 sim_fpu_to32i (&res, &op1, sim_fpu_round_near); 352 return res; 353 } 354 355 static SI 356 fixdfsi (CGEN_FPU* fpu, int how UNUSED, DF x) 357 { 358 sim_fpu op1; 359 unsigned32 res; 360 361 sim_fpu_64to (&op1, x); 362 sim_fpu_to32i (&res, &op1, sim_fpu_round_near); 363 return res; 364 } 365 366 static USI 367 ufixsfsi (CGEN_FPU* fpu, int how UNUSED, SF x) 368 { 369 sim_fpu op1; 370 unsigned32 res; 371 372 sim_fpu_32to (&op1, x); 373 sim_fpu_to32u (&res, &op1, sim_fpu_round_near); 374 return res; 375 } 376 377 /* DF mode support */ 378 379 static DF 380 adddf (CGEN_FPU* fpu, DF x, DF y) 381 { 382 sim_fpu op1; 383 sim_fpu op2; 384 sim_fpu ans; 385 unsigned64 res; 386 sim_fpu_status status; 387 388 sim_fpu_64to (&op1, x); 389 sim_fpu_64to (&op2, y); 390 status = sim_fpu_add (&ans, &op1, &op2); 391 if (status != 0) 392 (*fpu->ops->error) (fpu, status); 393 sim_fpu_to64 (&res, &ans); 394 395 return res; 396 } 397 398 static DF 399 subdf (CGEN_FPU* fpu, DF x, DF y) 400 { 401 sim_fpu op1; 402 sim_fpu op2; 403 sim_fpu ans; 404 unsigned64 res; 405 sim_fpu_status status; 406 407 sim_fpu_64to (&op1, x); 408 sim_fpu_64to (&op2, y); 409 status = sim_fpu_sub (&ans, &op1, &op2); 410 if (status != 0) 411 (*fpu->ops->error) (fpu, status); 412 sim_fpu_to64 (&res, &ans); 413 414 return res; 415 } 416 417 static DF 418 muldf (CGEN_FPU* fpu, DF x, DF y) 419 { 420 sim_fpu op1; 421 sim_fpu op2; 422 sim_fpu ans; 423 unsigned64 res; 424 sim_fpu_status status; 425 426 sim_fpu_64to (&op1, x); 427 sim_fpu_64to (&op2, y); 428 status = sim_fpu_mul (&ans, &op1, &op2); 429 if (status != 0) 430 (*fpu->ops->error) (fpu, status); 431 sim_fpu_to64 (&res, &ans); 432 433 return res; 434 } 435 436 static DF 437 divdf (CGEN_FPU* fpu, DF x, DF y) 438 { 439 sim_fpu op1; 440 sim_fpu op2; 441 sim_fpu ans; 442 unsigned64 res; 443 sim_fpu_status status; 444 445 sim_fpu_64to (&op1, x); 446 sim_fpu_64to (&op2, y); 447 status = sim_fpu_div (&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 negdf (CGEN_FPU* fpu, DF x) 457 { 458 sim_fpu op1; 459 sim_fpu ans; 460 unsigned64 res; 461 sim_fpu_status status; 462 463 sim_fpu_64to (&op1, x); 464 status = sim_fpu_neg (&ans, &op1); 465 if (status != 0) 466 (*fpu->ops->error) (fpu, status); 467 sim_fpu_to64 (&res, &ans); 468 469 return res; 470 } 471 472 static DF 473 absdf (CGEN_FPU* fpu, DF x) 474 { 475 sim_fpu op1; 476 sim_fpu ans; 477 unsigned64 res; 478 sim_fpu_status status; 479 480 sim_fpu_64to (&op1, x); 481 status = sim_fpu_abs (&ans, &op1); 482 if (status != 0) 483 (*fpu->ops->error) (fpu, status); 484 sim_fpu_to64 (&res, &ans); 485 486 return res; 487 } 488 489 static DF 490 sqrtdf (CGEN_FPU* fpu, DF x) 491 { 492 sim_fpu op1; 493 sim_fpu ans; 494 unsigned64 res; 495 sim_fpu_status status; 496 497 sim_fpu_64to (&op1, x); 498 status = sim_fpu_sqrt (&ans, &op1); 499 if (status != 0) 500 (*fpu->ops->error) (fpu, status); 501 sim_fpu_to64 (&res, &ans); 502 503 return res; 504 } 505 506 static DF 507 invdf (CGEN_FPU* fpu, DF x) 508 { 509 sim_fpu op1; 510 sim_fpu ans; 511 unsigned64 res; 512 sim_fpu_status status; 513 514 sim_fpu_64to (&op1, x); 515 status = sim_fpu_inv (&ans, &op1); 516 if (status != 0) 517 (*fpu->ops->error) (fpu, status); 518 sim_fpu_to64 (&res, &ans); 519 520 return res; 521 } 522 523 static DF 524 mindf (CGEN_FPU* fpu, DF x, DF y) 525 { 526 sim_fpu op1; 527 sim_fpu op2; 528 sim_fpu ans; 529 unsigned64 res; 530 sim_fpu_status status; 531 532 sim_fpu_64to (&op1, x); 533 sim_fpu_64to (&op2, y); 534 status = sim_fpu_min (&ans, &op1, &op2); 535 if (status != 0) 536 (*fpu->ops->error) (fpu, status); 537 sim_fpu_to64 (&res, &ans); 538 539 return res; 540 } 541 542 static DF 543 maxdf (CGEN_FPU* fpu, DF x, DF y) 544 { 545 sim_fpu op1; 546 sim_fpu op2; 547 sim_fpu ans; 548 unsigned64 res; 549 sim_fpu_status status; 550 551 sim_fpu_64to (&op1, x); 552 sim_fpu_64to (&op2, y); 553 status = sim_fpu_max (&ans, &op1, &op2); 554 if (status != 0) 555 (*fpu->ops->error) (fpu, status); 556 sim_fpu_to64 (&res, &ans); 557 558 return res; 559 } 560 561 static CGEN_FP_CMP 562 cmpdf (CGEN_FPU* fpu, DF x, DF y) 563 { 564 sim_fpu op1; 565 sim_fpu op2; 566 567 sim_fpu_64to (&op1, x); 568 sim_fpu_64to (&op2, y); 569 570 if (sim_fpu_is_nan (&op1) 571 || sim_fpu_is_nan (&op2)) 572 return FP_CMP_NAN; 573 574 if (x < y) 575 return FP_CMP_LT; 576 if (x > y) 577 return FP_CMP_GT; 578 return FP_CMP_EQ; 579 } 580 581 static int 582 eqdf (CGEN_FPU* fpu, DF x, DF y) 583 { 584 sim_fpu op1; 585 sim_fpu op2; 586 587 sim_fpu_64to (&op1, x); 588 sim_fpu_64to (&op2, y); 589 return sim_fpu_is_eq (&op1, &op2); 590 } 591 592 static int 593 nedf (CGEN_FPU* fpu, DF x, DF y) 594 { 595 sim_fpu op1; 596 sim_fpu op2; 597 598 sim_fpu_64to (&op1, x); 599 sim_fpu_64to (&op2, y); 600 return sim_fpu_is_ne (&op1, &op2); 601 } 602 603 static int 604 ltdf (CGEN_FPU* fpu, DF x, DF y) 605 { 606 sim_fpu op1; 607 sim_fpu op2; 608 609 sim_fpu_64to (&op1, x); 610 sim_fpu_64to (&op2, y); 611 return sim_fpu_is_lt (&op1, &op2); 612 } 613 614 static int 615 ledf (CGEN_FPU* fpu, DF x, DF y) 616 { 617 sim_fpu op1; 618 sim_fpu op2; 619 620 sim_fpu_64to (&op1, x); 621 sim_fpu_64to (&op2, y); 622 return sim_fpu_is_le (&op1, &op2); 623 } 624 625 static int 626 gtdf (CGEN_FPU* fpu, DF x, DF y) 627 { 628 sim_fpu op1; 629 sim_fpu op2; 630 631 sim_fpu_64to (&op1, x); 632 sim_fpu_64to (&op2, y); 633 return sim_fpu_is_gt (&op1, &op2); 634 } 635 636 static int 637 gedf (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 return sim_fpu_is_ge (&op1, &op2); 645 } 646 647 /* Initialize FP_OPS to use accurate library. */ 648 649 void 650 cgen_init_accurate_fpu (SIM_CPU* cpu, CGEN_FPU* fpu, CGEN_FPU_ERROR_FN* error) 651 { 652 CGEN_FP_OPS* o; 653 654 fpu->owner = cpu; 655 /* ??? small memory leak, not freed by sim_close */ 656 fpu->ops = (CGEN_FP_OPS*) xmalloc (sizeof (CGEN_FP_OPS)); 657 658 o = fpu->ops; 659 memset (o, 0, sizeof (*o)); 660 661 o->error = error; 662 663 o->addsf = addsf; 664 o->subsf = subsf; 665 o->mulsf = mulsf; 666 o->divsf = divsf; 667 o->negsf = negsf; 668 o->abssf = abssf; 669 o->sqrtsf = sqrtsf; 670 o->invsf = invsf; 671 o->minsf = minsf; 672 o->maxsf = maxsf; 673 o->cmpsf = cmpsf; 674 o->eqsf = eqsf; 675 o->nesf = nesf; 676 o->ltsf = ltsf; 677 o->lesf = lesf; 678 o->gtsf = gtsf; 679 o->gesf = gesf; 680 681 o->adddf = adddf; 682 o->subdf = subdf; 683 o->muldf = muldf; 684 o->divdf = divdf; 685 o->negdf = negdf; 686 o->absdf = absdf; 687 o->sqrtdf = sqrtdf; 688 o->invdf = invdf; 689 o->mindf = mindf; 690 o->maxdf = maxdf; 691 o->cmpdf = cmpdf; 692 o->eqdf = eqdf; 693 o->nedf = nedf; 694 o->ltdf = ltdf; 695 o->ledf = ledf; 696 o->gtdf = gtdf; 697 o->gedf = gedf; 698 o->fextsfdf = fextsfdf; 699 o->ftruncdfsf = ftruncdfsf; 700 o->floatsisf = floatsisf; 701 o->floatsidf = floatsidf; 702 o->ufloatsisf = ufloatsisf; 703 o->fixsfsi = fixsfsi; 704 o->fixdfsi = fixdfsi; 705 o->ufixsfsi = ufixsfsi; 706 } 707