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 19static SF 20addsf (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 38static SF 39subsf (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 57static SF 58mulsf (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 76static SF 77divsf (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 95static SF 96negsf (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 112static SF 113abssf (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 129static SF 130sqrtsf (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 146static SF 147invsf (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 163static SF 164minsf (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 182static SF 183maxsf (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 201static CGEN_FP_CMP 202cmpsf (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 221static int 222eqsf (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 232static int 233nesf (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 243static int 244ltsf (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 254static int 255lesf (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 265static int 266gtsf (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 276static int 277gesf (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 287static DF 288fextsfdf (CGEN_FPU* fpu, 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 299static SF 300ftruncdfsf (CGEN_FPU* fpu, 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 311static SF 312floatsisf (CGEN_FPU* fpu, 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 322static DF 323floatsidf (CGEN_FPU* fpu, 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 333static SF 334ufloatsisf (CGEN_FPU* fpu, 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 344static SI 345fixsfsi (CGEN_FPU* fpu, 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 355static SI 356fixdfsi (CGEN_FPU* fpu, 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 366static USI 367ufixsfsi (CGEN_FPU* fpu, 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 379static DF 380adddf (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 398static DF 399subdf (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 417static DF 418muldf (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 436static DF 437divdf (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 455static DF 456negdf (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 472static DF 473absdf (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 489static DF 490sqrtdf (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 506static DF 507invdf (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 523static DF 524mindf (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 542static DF 543maxdf (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 561static CGEN_FP_CMP 562cmpdf (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 581static int 582eqdf (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 592static int 593nedf (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 603static int 604ltdf (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 614static int 615ledf (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 625static int 626gtdf (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 636static int 637gedf (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 649void 650cgen_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