1/* 2 * Copyright (c) 1992 Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Ralph Campbell. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)fp.s 7.1 (Berkeley) 01/07/92 11 */ 12 13/* 14 * Standard header stuff. 15 */ 16 17#include "machine/regdef.h" 18#include "machine/machAsmDefs.h" 19#include "machine/machConst.h" 20#include "assym.h" 21 22#define SEXP_INF 0xff 23#define DEXP_INF 0x7ff 24#define SEXP_BIAS 127 25#define DEXP_BIAS 1023 26#define SEXP_MIN -126 27#define DEXP_MIN -1022 28#define SEXP_MAX 127 29#define DEXP_MAX 1023 30#define WEXP_MAX 30 /* maximum unbiased exponent for int */ 31#define WEXP_MIN -1 /* minimum unbiased exponent for int */ 32#define SFRAC_BITS 23 33#define DFRAC_BITS 52 34#define SIMPL_ONE 0x00800000 35#define DIMPL_ONE 0x00100000 36#define SLEAD_ZEROS 31 - 23 37#define DLEAD_ZEROS 31 - 20 38#define STICKYBIT 1 39#define GUARDBIT 0x80000000 40#define SSIGNAL_NAN 0x00400000 41#define DSIGNAL_NAN 0x00040000 42#define SQUIET_NAN 0x003fffff 43#define DQUIET_NAN0 0x0007ffff 44#define DQUIET_NAN1 0xffffffff 45#define INT_MIN 0x80000000 46#define INT_MAX 0x7fffffff 47 48#define COND_UNORDERED 0x1 49#define COND_EQUAL 0x2 50#define COND_LESS 0x4 51#define COND_SIGNAL 0x8 52 53/*---------------------------------------------------------------------------- 54 * 55 * MachEmulateFP -- 56 * 57 * Emulate unimplemented floating point operations. 58 * This routine should only be called by MachFPInterrupt(). 59 * 60 * MachEmulateFP(instr) 61 * unsigned instr; 62 * 63 * Results: 64 * None. 65 * 66 * Side effects: 67 * Floating point registers are modified according to instruction. 68 * 69 *---------------------------------------------------------------------------- 70 */ 71NON_LEAF(MachEmulateFP, STAND_FRAME_SIZE, ra) 72 subu sp, sp, STAND_FRAME_SIZE 73 sw ra, STAND_RA_OFFSET(sp) 74/* 75 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0). 76 */ 77 srl v0, a0, 21 - 2 # get FMT field 78 and v0, v0, 0xF << 2 # mask FMT field 79 and v1, a0, 0x3F # mask FUNC field 80 sll v1, v1, 5 # align for table lookup 81 bgt v0, 4 << 2, ill # illegal format 82 83 or v1, v1, v0 84 cfc1 a1, MACH_FPC_CSR # get exception register 85 lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT 86 and a1, a1, ~MACH_FPC_EXCEPTION_UNIMPL # clear exception 87 ctc1 a1, MACH_FPC_CSR 88 j a3 89 90 .rdata 91func_fmt_tbl: 92 .word add_s # 0 93 .word add_d # 0 94 .word ill # 0 95 .word ill # 0 96 .word ill # 0 97 .word ill # 0 98 .word ill # 0 99 .word ill # 0 100 .word sub_s # 1 101 .word sub_d # 1 102 .word ill # 1 103 .word ill # 1 104 .word ill # 1 105 .word ill # 1 106 .word ill # 1 107 .word ill # 1 108 .word mul_s # 2 109 .word mul_d # 2 110 .word ill # 2 111 .word ill # 2 112 .word ill # 2 113 .word ill # 2 114 .word ill # 2 115 .word ill # 2 116 .word div_s # 3 117 .word div_d # 3 118 .word ill # 3 119 .word ill # 3 120 .word ill # 3 121 .word ill # 3 122 .word ill # 3 123 .word ill # 3 124 .word ill # 4 125 .word ill # 4 126 .word ill # 4 127 .word ill # 4 128 .word ill # 4 129 .word ill # 4 130 .word ill # 4 131 .word ill # 4 132 .word abs_s # 5 133 .word abs_d # 5 134 .word ill # 5 135 .word ill # 5 136 .word ill # 5 137 .word ill # 5 138 .word ill # 5 139 .word ill # 5 140 .word mov_s # 6 141 .word mov_d # 6 142 .word ill # 6 143 .word ill # 6 144 .word ill # 6 145 .word ill # 6 146 .word ill # 6 147 .word ill # 6 148 .word neg_s # 7 149 .word neg_d # 7 150 .word ill # 7 151 .word ill # 7 152 .word ill # 7 153 .word ill # 7 154 .word ill # 7 155 .word ill # 7 156 .word ill # 8 157 .word ill # 8 158 .word ill # 8 159 .word ill # 8 160 .word ill # 8 161 .word ill # 8 162 .word ill # 8 163 .word ill # 8 164 .word ill # 9 165 .word ill # 9 166 .word ill # 9 167 .word ill # 9 168 .word ill # 9 169 .word ill # 9 170 .word ill # 9 171 .word ill # 9 172 .word ill # 10 173 .word ill # 10 174 .word ill # 10 175 .word ill # 10 176 .word ill # 10 177 .word ill # 10 178 .word ill # 10 179 .word ill # 10 180 .word ill # 11 181 .word ill # 11 182 .word ill # 11 183 .word ill # 11 184 .word ill # 11 185 .word ill # 11 186 .word ill # 11 187 .word ill # 11 188 .word ill # 12 189 .word ill # 12 190 .word ill # 12 191 .word ill # 12 192 .word ill # 12 193 .word ill # 12 194 .word ill # 12 195 .word ill # 12 196 .word ill # 13 197 .word ill # 13 198 .word ill # 13 199 .word ill # 13 200 .word ill # 13 201 .word ill # 13 202 .word ill # 13 203 .word ill # 13 204 .word ill # 14 205 .word ill # 14 206 .word ill # 14 207 .word ill # 14 208 .word ill # 14 209 .word ill # 14 210 .word ill # 14 211 .word ill # 14 212 .word ill # 15 213 .word ill # 15 214 .word ill # 15 215 .word ill # 15 216 .word ill # 15 217 .word ill # 15 218 .word ill # 15 219 .word ill # 15 220 .word ill # 16 221 .word ill # 16 222 .word ill # 16 223 .word ill # 16 224 .word ill # 16 225 .word ill # 16 226 .word ill # 16 227 .word ill # 16 228 .word ill # 17 229 .word ill # 17 230 .word ill # 17 231 .word ill # 17 232 .word ill # 17 233 .word ill # 17 234 .word ill # 17 235 .word ill # 17 236 .word ill # 18 237 .word ill # 18 238 .word ill # 18 239 .word ill # 18 240 .word ill # 18 241 .word ill # 18 242 .word ill # 18 243 .word ill # 18 244 .word ill # 19 245 .word ill # 19 246 .word ill # 19 247 .word ill # 19 248 .word ill # 19 249 .word ill # 19 250 .word ill # 19 251 .word ill # 19 252 .word ill # 20 253 .word ill # 20 254 .word ill # 20 255 .word ill # 20 256 .word ill # 20 257 .word ill # 20 258 .word ill # 20 259 .word ill # 20 260 .word ill # 21 261 .word ill # 21 262 .word ill # 21 263 .word ill # 21 264 .word ill # 21 265 .word ill # 21 266 .word ill # 21 267 .word ill # 21 268 .word ill # 22 269 .word ill # 22 270 .word ill # 22 271 .word ill # 22 272 .word ill # 22 273 .word ill # 22 274 .word ill # 22 275 .word ill # 22 276 .word ill # 23 277 .word ill # 23 278 .word ill # 23 279 .word ill # 23 280 .word ill # 23 281 .word ill # 23 282 .word ill # 23 283 .word ill # 23 284 .word ill # 24 285 .word ill # 24 286 .word ill # 24 287 .word ill # 24 288 .word ill # 24 289 .word ill # 24 290 .word ill # 24 291 .word ill # 24 292 .word ill # 25 293 .word ill # 25 294 .word ill # 25 295 .word ill # 25 296 .word ill # 25 297 .word ill # 25 298 .word ill # 25 299 .word ill # 25 300 .word ill # 26 301 .word ill # 26 302 .word ill # 26 303 .word ill # 26 304 .word ill # 26 305 .word ill # 26 306 .word ill # 26 307 .word ill # 26 308 .word ill # 27 309 .word ill # 27 310 .word ill # 27 311 .word ill # 27 312 .word ill # 27 313 .word ill # 27 314 .word ill # 27 315 .word ill # 27 316 .word ill # 28 317 .word ill # 28 318 .word ill # 28 319 .word ill # 28 320 .word ill # 28 321 .word ill # 28 322 .word ill # 28 323 .word ill # 28 324 .word ill # 29 325 .word ill # 29 326 .word ill # 29 327 .word ill # 29 328 .word ill # 29 329 .word ill # 29 330 .word ill # 29 331 .word ill # 29 332 .word ill # 30 333 .word ill # 30 334 .word ill # 30 335 .word ill # 30 336 .word ill # 30 337 .word ill # 30 338 .word ill # 30 339 .word ill # 30 340 .word ill # 31 341 .word ill # 31 342 .word ill # 31 343 .word ill # 31 344 .word ill # 31 345 .word ill # 31 346 .word ill # 31 347 .word ill # 31 348 .word ill # 32 349 .word cvt_s_d # 32 350 .word ill # 32 351 .word ill # 32 352 .word cvt_s_w # 32 353 .word ill # 32 354 .word ill # 32 355 .word ill # 32 356 .word cvt_d_s # 33 357 .word ill # 33 358 .word ill # 33 359 .word ill # 33 360 .word cvt_d_w # 33 361 .word ill # 33 362 .word ill # 33 363 .word ill # 33 364 .word ill # 34 365 .word ill # 34 366 .word ill # 34 367 .word ill # 34 368 .word ill # 34 369 .word ill # 34 370 .word ill # 34 371 .word ill # 34 372 .word ill # 35 373 .word ill # 35 374 .word ill # 35 375 .word ill # 35 376 .word ill # 35 377 .word ill # 35 378 .word ill # 35 379 .word ill # 35 380 .word cvt_w_s # 36 381 .word cvt_w_d # 36 382 .word ill # 36 383 .word ill # 36 384 .word ill # 36 385 .word ill # 36 386 .word ill # 36 387 .word ill # 36 388 .word ill # 37 389 .word ill # 37 390 .word ill # 37 391 .word ill # 37 392 .word ill # 37 393 .word ill # 37 394 .word ill # 37 395 .word ill # 37 396 .word ill # 38 397 .word ill # 38 398 .word ill # 38 399 .word ill # 38 400 .word ill # 38 401 .word ill # 38 402 .word ill # 38 403 .word ill # 38 404 .word ill # 39 405 .word ill # 39 406 .word ill # 39 407 .word ill # 39 408 .word ill # 39 409 .word ill # 39 410 .word ill # 39 411 .word ill # 39 412 .word ill # 40 413 .word ill # 40 414 .word ill # 40 415 .word ill # 40 416 .word ill # 40 417 .word ill # 40 418 .word ill # 40 419 .word ill # 40 420 .word ill # 41 421 .word ill # 41 422 .word ill # 41 423 .word ill # 41 424 .word ill # 41 425 .word ill # 41 426 .word ill # 41 427 .word ill # 41 428 .word ill # 42 429 .word ill # 42 430 .word ill # 42 431 .word ill # 42 432 .word ill # 42 433 .word ill # 42 434 .word ill # 42 435 .word ill # 42 436 .word ill # 43 437 .word ill # 43 438 .word ill # 43 439 .word ill # 43 440 .word ill # 43 441 .word ill # 43 442 .word ill # 43 443 .word ill # 43 444 .word ill # 44 445 .word ill # 44 446 .word ill # 44 447 .word ill # 44 448 .word ill # 44 449 .word ill # 44 450 .word ill # 44 451 .word ill # 44 452 .word ill # 45 453 .word ill # 45 454 .word ill # 45 455 .word ill # 45 456 .word ill # 45 457 .word ill # 45 458 .word ill # 45 459 .word ill # 45 460 .word ill # 46 461 .word ill # 46 462 .word ill # 46 463 .word ill # 46 464 .word ill # 46 465 .word ill # 46 466 .word ill # 46 467 .word ill # 46 468 .word ill # 47 469 .word ill # 47 470 .word ill # 47 471 .word ill # 47 472 .word ill # 47 473 .word ill # 47 474 .word ill # 47 475 .word ill # 47 476 .word cmp_s # 48 477 .word cmp_d # 48 478 .word ill # 48 479 .word ill # 48 480 .word ill # 48 481 .word ill # 48 482 .word ill # 48 483 .word ill # 48 484 .word cmp_s # 49 485 .word cmp_d # 49 486 .word ill # 49 487 .word ill # 49 488 .word ill # 49 489 .word ill # 49 490 .word ill # 49 491 .word ill # 49 492 .word cmp_s # 50 493 .word cmp_d # 50 494 .word ill # 50 495 .word ill # 50 496 .word ill # 50 497 .word ill # 50 498 .word ill # 50 499 .word ill # 50 500 .word cmp_s # 51 501 .word cmp_d # 51 502 .word ill # 51 503 .word ill # 51 504 .word ill # 51 505 .word ill # 51 506 .word ill # 51 507 .word ill # 51 508 .word cmp_s # 52 509 .word cmp_d # 52 510 .word ill # 52 511 .word ill # 52 512 .word ill # 52 513 .word ill # 52 514 .word ill # 52 515 .word ill # 52 516 .word cmp_s # 53 517 .word cmp_d # 53 518 .word ill # 53 519 .word ill # 53 520 .word ill # 53 521 .word ill # 53 522 .word ill # 53 523 .word ill # 53 524 .word cmp_s # 54 525 .word cmp_d # 54 526 .word ill # 54 527 .word ill # 54 528 .word ill # 54 529 .word ill # 54 530 .word ill # 54 531 .word ill # 54 532 .word cmp_s # 55 533 .word cmp_d # 55 534 .word ill # 55 535 .word ill # 55 536 .word ill # 55 537 .word ill # 55 538 .word ill # 55 539 .word ill # 55 540 .word cmp_s # 56 541 .word cmp_d # 56 542 .word ill # 56 543 .word ill # 56 544 .word ill # 56 545 .word ill # 56 546 .word ill # 56 547 .word ill # 56 548 .word cmp_s # 57 549 .word cmp_d # 57 550 .word ill # 57 551 .word ill # 57 552 .word ill # 57 553 .word ill # 57 554 .word ill # 57 555 .word ill # 57 556 .word cmp_s # 58 557 .word cmp_d # 58 558 .word ill # 58 559 .word ill # 58 560 .word ill # 58 561 .word ill # 58 562 .word ill # 58 563 .word ill # 58 564 .word cmp_s # 59 565 .word cmp_d # 59 566 .word ill # 59 567 .word ill # 59 568 .word ill # 59 569 .word ill # 59 570 .word ill # 59 571 .word ill # 59 572 .word cmp_s # 60 573 .word cmp_d # 60 574 .word ill # 60 575 .word ill # 60 576 .word ill # 60 577 .word ill # 60 578 .word ill # 60 579 .word ill # 60 580 .word cmp_s # 61 581 .word cmp_d # 61 582 .word ill # 61 583 .word ill # 61 584 .word ill # 61 585 .word ill # 61 586 .word ill # 61 587 .word ill # 61 588 .word cmp_s # 62 589 .word cmp_d # 62 590 .word ill # 62 591 .word ill # 62 592 .word ill # 62 593 .word ill # 62 594 .word ill # 62 595 .word ill # 62 596 .word cmp_s # 63 597 .word cmp_d # 63 598 .word ill # 63 599 .word ill # 63 600 .word ill # 63 601 .word ill # 63 602 .word ill # 63 603 .word ill # 63 604 .text 605 606/* 607 * Single precision subtract. 608 */ 609sub_s: 610 jal get_fs_sgl 611 jal get_ft_sgl 612 xor t4, t4, 1 # negate FT sign bit 613 b add_sub_s 614/* 615 * Single precision add. 616 */ 617add_s: 618 jal get_fs_sgl 619 jal get_ft_sgl 620add_sub_s: 621 bne t1, SEXP_INF, 1f # is FS an infinity? 622 bne t5, SEXP_INF, result_fs_s # if FT is not inf, result=FS 623 bne t0, t4, invalid_s # both infinities same sign? 624 b result_fs_s # result is in FS 6251: 626 beq t5, SEXP_INF, result_ft_s # if FT is inf, result=FT 627 bne t1, zero, 4f # is FS a denormalized num? 628 beq t2, zero, 3f # is FS zero? 629 bne t5, zero, 2f # is FT a denormalized num? 630 beq t6, zero, result_fs_s # FT is zero, result=FS 631 jal renorm_fs_s 632 jal renorm_ft_s 633 b 5f 6342: 635 jal renorm_fs_s 636 subu t5, t5, SEXP_BIAS # unbias FT exponent 637 or t6, t6, SIMPL_ONE # set implied one bit 638 b 5f 6393: 640 bne t5, zero, result_ft_s # if FT != 0, result=FT 641 bne t6, zero, result_ft_s 642 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 643 bne v0, MACH_FPC_ROUND_RM, 1f # round to -infinity? 644 or t0, t0, t4 # compute result sign 645 b result_fs_s 6461: 647 and t0, t0, t4 # compute result sign 648 b result_fs_s 6494: 650 bne t5, zero, 2f # is FT a denormalized num? 651 beq t6, zero, result_fs_s # FT is zero, result=FS 652 subu t1, t1, SEXP_BIAS # unbias FS exponent 653 or t2, t2, SIMPL_ONE # set implied one bit 654 jal renorm_ft_s 655 b 5f 6562: 657 subu t1, t1, SEXP_BIAS # unbias FS exponent 658 or t2, t2, SIMPL_ONE # set implied one bit 659 subu t5, t5, SEXP_BIAS # unbias FT exponent 660 or t6, t6, SIMPL_ONE # set implied one bit 661/* 662 * Perform the addition. 663 */ 6645: 665 move t8, zero # no shifted bits (sticky reg) 666 beq t1, t5, 4f # no shift needed 667 subu v0, t1, t5 # v0 = difference of exponents 668 move v1, v0 # v1 = abs(difference) 669 bge v0, zero, 1f 670 negu v1 6711: 672 ble v1, SFRAC_BITS+2, 2f # is difference too great? 673 li t8, STICKYBIT # set the sticky bit 674 bge v0, zero, 1f # check which exp is larger 675 move t1, t5 # result exp is FT's 676 move t2, zero # FS's fraction shifted is zero 677 b 4f 6781: 679 move t6, zero # FT's fraction shifted is zero 680 b 4f 6812: 682 li t9, 32 # compute 32 - abs(exp diff) 683 subu t9, t9, v1 684 bgt v0, zero, 3f # if FS > FT, shift FT's frac 685 move t1, t5 # FT > FS, result exp is FT's 686 sll t8, t2, t9 # save bits shifted out 687 srl t2, t2, v1 # shift FS's fraction 688 b 4f 6893: 690 sll t8, t6, t9 # save bits shifted out 691 srl t6, t6, v1 # shift FT's fraction 6924: 693 bne t0, t4, 1f # if signs differ, subtract 694 addu t2, t2, t6 # add fractions 695 b norm_s 6961: 697 blt t2, t6, 3f # subtract larger from smaller 698 bne t2, t6, 2f # if same, result=0 699 move t1, zero # result=0 700 move t2, zero 701 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 702 bne v0, MACH_FPC_ROUND_RM, 1f # round to -infinity? 703 or t0, t0, t4 # compute result sign 704 b result_fs_s 7051: 706 and t0, t0, t4 # compute result sign 707 b result_fs_s 7082: 709 sltu t9, zero, t8 # compute t2:zero - t6:t8 710 subu t8, zero, t8 711 subu t2, t2, t6 # subtract fractions 712 subu t2, t2, t9 # subtract barrow 713 b norm_s 7143: 715 move t0, t4 # sign of result = FT's 716 sltu t9, zero, t8 # compute t6:zero - t2:t8 717 subu t8, zero, t8 718 subu t2, t6, t2 # subtract fractions 719 subu t2, t2, t9 # subtract barrow 720 b norm_s 721 722/* 723 * Double precision subtract. 724 */ 725sub_d: 726 jal get_fs_dbl 727 jal get_ft_dbl 728 xor t4, t4, 1 # negate sign bit 729 b add_sub_d 730/* 731 * Double precision add. 732 */ 733add_d: 734 jal get_fs_dbl 735 jal get_ft_dbl 736add_sub_d: 737 bne t1, DEXP_INF, 1f # is FS an infinity? 738 bne t5, DEXP_INF, result_fs_d # if FT is not inf, result=FS 739 bne t0, t4, invalid_d # both infinities same sign? 740 b result_fs_d # result is in FS 7411: 742 beq t5, DEXP_INF, result_ft_d # if FT is inf, result=FT 743 bne t1, zero, 4f # is FS a denormalized num? 744 bne t2, zero, 1f # is FS zero? 745 beq t3, zero, 3f 7461: 747 bne t5, zero, 2f # is FT a denormalized num? 748 bne t6, zero, 1f 749 beq t7, zero, result_fs_d # FT is zero, result=FS 7501: 751 jal renorm_fs_d 752 jal renorm_ft_d 753 b 5f 7542: 755 jal renorm_fs_d 756 subu t5, t5, DEXP_BIAS # unbias FT exponent 757 or t6, t6, DIMPL_ONE # set implied one bit 758 b 5f 7593: 760 bne t5, zero, result_ft_d # if FT != 0, result=FT 761 bne t6, zero, result_ft_d 762 bne t7, zero, result_ft_d 763 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 764 bne v0, MACH_FPC_ROUND_RM, 1f # round to -infinity? 765 or t0, t0, t4 # compute result sign 766 b result_fs_d 7671: 768 and t0, t0, t4 # compute result sign 769 b result_fs_d 7704: 771 bne t5, zero, 2f # is FT a denormalized num? 772 bne t6, zero, 1f 773 beq t7, zero, result_fs_d # FT is zero, result=FS 7741: 775 subu t1, t1, DEXP_BIAS # unbias FS exponent 776 or t2, t2, DIMPL_ONE # set implied one bit 777 jal renorm_ft_d 778 b 5f 7792: 780 subu t1, t1, DEXP_BIAS # unbias FS exponent 781 or t2, t2, DIMPL_ONE # set implied one bit 782 subu t5, t5, DEXP_BIAS # unbias FT exponent 783 or t6, t6, DIMPL_ONE # set implied one bit 784/* 785 * Perform the addition. 786 */ 7875: 788 move t8, zero # no shifted bits (sticky reg) 789 beq t1, t5, 4f # no shift needed 790 subu v0, t1, t5 # v0 = difference of exponents 791 move v1, v0 # v1 = abs(difference) 792 bge v0, zero, 1f 793 negu v1 7941: 795 ble v1, DFRAC_BITS+2, 2f # is difference too great? 796 li t8, STICKYBIT # set the sticky bit 797 bge v0, zero, 1f # check which exp is larger 798 move t1, t5 # result exp is FT's 799 move t2, zero # FS's fraction shifted is zero 800 move t3, zero 801 b 4f 8021: 803 move t6, zero # FT's fraction shifted is zero 804 move t7, zero 805 b 4f 8062: 807 li t9, 32 808 bge v0, zero, 3f # if FS > FT, shift FT's frac 809 move t1, t5 # FT > FS, result exp is FT's 810 blt v1, t9, 1f # shift right by < 32? 811 subu v1, v1, t9 812 subu t9, t9, v1 813 sll t8, t2, t9 # save bits shifted out 814 sltu t9, zero, t3 # don't lose any one bits 815 or t8, t8, t9 # save sticky bit 816 srl t3, t2, v1 # shift FS's fraction 817 move t2, zero 818 b 4f 8191: 820 subu t9, t9, v1 821 sll t8, t3, t9 # save bits shifted out 822 srl t3, t3, v1 # shift FS's fraction 823 sll t9, t2, t9 # save bits shifted out of t2 824 or t3, t3, t9 # and put into t3 825 srl t2, t2, v1 826 b 4f 8273: 828 blt v1, t9, 1f # shift right by < 32? 829 subu v1, v1, t9 830 subu t9, t9, v1 831 sll t8, t6, t9 # save bits shifted out 832 srl t7, t6, v1 # shift FT's fraction 833 move t6, zero 834 b 4f 8351: 836 subu t9, t9, v1 837 sll t8, t7, t9 # save bits shifted out 838 srl t7, t7, v1 # shift FT's fraction 839 sll t9, t6, t9 # save bits shifted out of t2 840 or t7, t7, t9 # and put into t3 841 srl t6, t6, v1 8424: 843 bne t0, t4, 1f # if signs differ, subtract 844 addu t3, t3, t7 # add fractions 845 sltu t9, t3, t7 # compute carry 846 addu t2, t2, t6 # add fractions 847 addu t2, t2, t9 # add carry 848 b norm_d 8491: 850 blt t2, t6, 3f # subtract larger from smaller 851 bne t2, t6, 2f 852 bltu t3, t7, 3f 853 bne t3, t7, 2f # if same, result=0 854 move t1, zero # result=0 855 move t2, zero 856 move t3, zero 857 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 858 bne v0, MACH_FPC_ROUND_RM, 1f # round to -infinity? 859 or t0, t0, t4 # compute result sign 860 b result_fs_d 8611: 862 and t0, t0, t4 # compute result sign 863 b result_fs_d 8642: 865 beq t8, zero, 1f # compute t2:t3:zero - t6:t7:t8 866 subu t8, zero, t8 867 sltu v0, t3, 1 # compute barrow out 868 subu t3, t3, 1 # subtract barrow 869 subu t2, t2, v0 8701: 871 sltu v0, t3, t7 872 subu t3, t3, t7 # subtract fractions 873 subu t2, t2, t6 # subtract fractions 874 subu t2, t2, v0 # subtract barrow 875 b norm_d 8763: 877 move t0, t4 # sign of result = FT's 878 beq t8, zero, 1f # compute t6:t7:zero - t2:t3:t8 879 subu t8, zero, t8 880 sltu v0, t7, 1 # compute barrow out 881 subu t7, t7, 1 # subtract barrow 882 subu t6, t6, v0 8831: 884 sltu v0, t7, t3 885 subu t3, t7, t3 # subtract fractions 886 subu t2, t6, t2 # subtract fractions 887 subu t2, t2, v0 # subtract barrow 888 b norm_d 889 890/* 891 * Single precision multiply. 892 */ 893mul_s: 894 jal get_fs_sgl 895 jal get_ft_sgl 896 xor t0, t0, t4 # compute sign of result 897 move t4, t0 # put in FT too 898 bne t1, SEXP_INF, 1f # is FS an infinity? 899 beq t5, SEXP_INF, result_fs_s # FS is inf, is FT an infinity? 900 bne t5, zero, result_fs_s # inf * zero? if no, result=FS 901 beq t6, zero, invalid_s # if yes, invalid operation 902 b result_fs_s 9031: 904 bne t5, SEXP_INF, 1f # FS != inf, is FT an infinity? 905 bne t1, zero, result_ft_s # zero * inf? if no, result=FT 906 beq t2, zero, invalid_s # if yes, invalid operation 907 b result_ft_s 9081: 909 bne t1, zero, 1f # is FS zero? 910 beq t2, zero, result_fs_s # result is zero 911 jal renorm_fs_s 912 b 2f 9131: 914 subu t1, t1, SEXP_BIAS # unbias FS exponent 915 or t2, t2, SIMPL_ONE # set implied one bit 9162: 917 bne t5, zero, 1f # is FT zero? 918 beq t6, zero, result_ft_s # result is zero 919 jal renorm_ft_s 920 b 2f 9211: 922 subu t5, t5, SEXP_BIAS # unbias FT exponent 923 or t6, t6, SIMPL_ONE # set implied one bit 9242: 925 addu t1, t1, t5 # compute result exponent 926 addu t1, t1, 9 # ??? 927 multu t2, t6 # multiply fractions 928 mflo t8 929 mfhi t2 930 b norm_s 931 932/* 933 * Double precision multiply. 934 */ 935mul_d: 936 jal get_fs_dbl 937 jal get_ft_dbl 938 xor t0, t0, t4 # compute sign of result 939 move t4, t0 # put in FT too 940 bne t1, DEXP_INF, 1f # is FS an infinity? 941 beq t5, DEXP_INF, result_fs_d # FS is inf, is FT an infinity? 942 bne t5, zero, result_fs_d # inf * zero? if no, result=FS 943 bne t6, zero, result_fs_d 944 beq t7, zero, invalid_d # if yes, invalid operation 945 b result_fs_d 9461: 947 bne t5, DEXP_INF, 1f # FS != inf, is FT an infinity? 948 bne t1, zero, result_ft_d # zero * inf? if no, result=FT 949 bne t2, zero, result_ft_d 950 beq t3, zero, invalid_d # if yes, invalid operation 951 b result_ft_d 9521: 953 bne t1, zero, 2f # is FS zero? 954 bne t2, zero, 1f 955 beq t3, zero, result_fs_d # result is zero 9561: 957 jal renorm_fs_d 958 b 3f 9592: 960 subu t1, t1, DEXP_BIAS # unbias FS exponent 961 or t2, t2, DIMPL_ONE # set implied one bit 9623: 963 bne t5, zero, 2f # is FT zero? 964 bne t6, zero, 1f 965 beq t7, zero, result_ft_d # result is zero 9661: 967 jal renorm_ft_d 968 b 3f 9692: 970 subu t5, t5, DEXP_BIAS # unbias FT exponent 971 or t6, t6, DIMPL_ONE # set implied one bit 9723: 973 addu t1, t1, t5 # compute result exponent 974 addu t1, t1, 12 # ??? 975 multu t3, t7 # multiply fractions (low * low) 976 move t4, t2 # free up t2,t3 for result 977 move t5, t3 978 mflo a3 # save low order bits 979 mfhi t8 980 not v0, t8 981 multu t4, t7 # multiply FS(high) * FT(low) 982 mflo v1 983 mfhi t3 # init low result 984 sltu v0, v0, v1 # compute carry 985 addu t8, v1 986 multu t5, t6 # multiply FS(low) * FT(high) 987 addu t3, t3, v0 # add carry 988 not v0, t8 989 mflo v1 990 mfhi t2 991 sltu v0, v0, v1 992 addu t8, v1 993 multu t4, t6 # multiply FS(high) * FT(high) 994 addu t3, v0 995 not v1, t3 996 sltu v1, v1, t2 997 addu t3, t2 998 not v0, t3 999 mfhi t2 1000 addu t2, v1 1001 mflo v1 1002 sltu v0, v0, v1 1003 addu t2, v0 1004 addu t3, v1 1005 sltu a3, zero, a3 # reduce t8,a3 to just t8 1006 or t8, a3 1007 b norm_d 1008 1009/* 1010 * Single precision divide. 1011 */ 1012div_s: 1013 jal get_fs_sgl 1014 jal get_ft_sgl 1015 xor t0, t0, t4 # compute sign of result 1016 bne t1, SEXP_INF, 1f # is FS an infinity? 1017 beq t5, SEXP_INF, invalid_s # is FT an infinity? 1018 b result_fs_s # result=infinity 10191: 1020 bne t5, SEXP_INF, 1f # is FT an infinity? 1021 move t2, zero # result = zero 1022 b result_fs_s 10231: 1024 bne t1, zero, 2f # is FS zero? 1025 bne t2, zero, 1f 1026 bne t5, zero, result_fs_s # FS=zero, is FT zero? 1027 beq t6, zero, invalid_s # 0 / 0 1028 b result_fs_s # result = zero 10291: 1030 jal renorm_fs_s 1031 b 3f 10322: 1033 subu t1, t1, SEXP_BIAS # unbias FS exponent 1034 or t2, t2, SIMPL_ONE # set implied one bit 10353: 1036 bne t5, zero, 2f # is FT zero? 1037 bne t6, zero, 1f 1038 or a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0 1039 and v0, a1, MACH_FPC_ENABLE_DIV0 # trap enabled? 1040 bne v0, zero, fpe_trap 1041 ctc1 a1, MACH_FPC_CSR # save exceptions 1042 li t1, SEXP_INF # result is infinity 1043 move t2, zero 1044 b result_fs_s 10451: 1046 jal renorm_ft_s 1047 b 3f 10482: 1049 subu t5, t5, SEXP_BIAS # unbias FT exponent 1050 or t6, t6, SIMPL_ONE # set implied one bit 10513: 1052 subu t1, t1, t5 # compute exponent 1053 subu t1, t1, 3 # compensate for result position 1054 li v0, SFRAC_BITS+3 # number of bits to divide 1055 move t8, t2 # init dividend 1056 move t2, zero # init result 10571: 1058 bltu t8, t6, 3f # is dividend >= divisor? 10592: 1060 subu t8, t8, t6 # subtract divisor from dividend 1061 or t2, t2, 1 # remember that we did 1062 bne t8, zero, 3f # if not done, continue 1063 sll t2, t2, v0 # shift result to final position 1064 b norm_s 10653: 1066 sll t8, t8, 1 # shift dividend 1067 sll t2, t2, 1 # shift result 1068 subu v0, v0, 1 # are we done? 1069 bne v0, zero, 1b # no, continue 1070 b norm_s 1071 1072/* 1073 * Double precision divide. 1074 */ 1075div_d: 1076 jal get_fs_dbl 1077 jal get_ft_dbl 1078 xor t0, t0, t4 # compute sign of result 1079 bne t1, DEXP_INF, 1f # is FS an infinity? 1080 beq t5, DEXP_INF, invalid_d # is FT an infinity? 1081 b result_fs_d # result=infinity 10821: 1083 bne t5, DEXP_INF, 1f # is FT an infinity? 1084 move t2, zero # x / infinity == zero 1085 move t3, zero 1086 b result_fs_d 10871: 1088 bne t1, zero, 2f # is FS zero? 1089 bne t2, zero, 1f 1090 bne t3, zero, 1f 1091 bne t5, zero, result_fs_d # FS=zero, is FT zero? 1092 bne t6, zero, result_fs_d 1093 beq t7, zero, invalid_d # 0 / 0 1094 b result_fs_d # result = zero 10951: 1096 jal renorm_fs_d 1097 b 3f 10982: 1099 subu t1, t1, DEXP_BIAS # unbias FS exponent 1100 or t2, t2, DIMPL_ONE # set implied one bit 11013: 1102 bne t5, zero, 2f # is FT zero? 1103 bne t6, zero, 1f 1104 bne t7, zero, 1f 1105 or a1, a1, MACH_FPC_EXCEPTION_DIV0 | MACH_FPC_STICKY_DIV0 1106 and v0, a1, MACH_FPC_ENABLE_DIV0 # trap enabled? 1107 bne v0, zero, fpe_trap 1108 ctc1 a1, MACH_FPC_CSR # Save exceptions 1109 li t1, DEXP_INF # result is infinity 1110 move t2, zero 1111 move t3, zero 1112 b result_fs_d 11131: 1114 jal renorm_ft_d 1115 b 3f 11162: 1117 subu t5, t5, DEXP_BIAS # unbias FT exponent 1118 or t6, t6, DIMPL_ONE # set implied one bit 11193: 1120 subu t1, t1, t5 # compute exponent 1121 subu t1, t1, 3 # compensate for result position 1122 li v0, DFRAC_BITS+3 # number of bits to divide 1123 move t8, t2 # init dividend 1124 move t9, t3 1125 move t2, zero # init result 1126 move t3, zero 11271: 1128 bltu t8, t6, 3f # is dividend >= divisor? 1129 bne t8, t6, 2f 1130 bltu t9, t7, 3f 11312: 1132 sltu v1, t9, t7 # subtract divisor from dividend 1133 subu t9, t9, t7 1134 subu t8, t8, t6 1135 subu t8, t8, v1 1136 or t3, t3, 1 # remember that we did 1137 bne t8, zero, 3f # if not done, continue 1138 bne t9, zero, 3f 1139 li v1, 32 # shift result to final position 1140 subu v1, v1, v0 1141 sll t2, t2, v0 # shift upper part 1142 srl t9, t3, v1 # save bits shifted out 1143 or t2, t2, t9 # and put into upper part 1144 sll t3, t3, v0 1145 b norm_d 11463: 1147 sll t8, t8, 1 # shift dividend 1148 srl v1, t9, 31 # save bit shifted out 1149 or t8, t8, v1 # and put into upper part 1150 sll t9, t9, 1 1151 sll t2, t2, 1 # shift result 1152 srl v1, t3, 31 # save bit shifted out 1153 or t2, t2, v1 # and put into upper part 1154 sll t3, t3, 1 1155 subu v0, v0, 1 # are we done? 1156 bne v0, zero, 1b # no, continue 1157 b norm_d 1158 1159/* 1160 * Single precision absolute value. 1161 */ 1162abs_s: 1163 jal get_fs_sgl 1164 move t0, zero # set sign positive 1165 b result_fs_s 1166 1167/* 1168 * Double precision absolute value. 1169 */ 1170abs_d: 1171 jal get_fs_dbl 1172 move t0, zero # set sign positive 1173 b result_fs_d 1174 1175/* 1176 * Single precision move. 1177 */ 1178mov_s: 1179 jal get_fs_sgl 1180 b result_fs_s 1181 1182/* 1183 * Double precision move. 1184 */ 1185mov_d: 1186 jal get_fs_dbl 1187 b result_fs_d 1188 1189/* 1190 * Single precision negate. 1191 */ 1192neg_s: 1193 jal get_fs_sgl 1194 xor t0, t0, 1 # reverse sign 1195 b result_fs_s 1196 1197/* 1198 * Double precision negate. 1199 */ 1200neg_d: 1201 jal get_fs_dbl 1202 xor t0, t0, 1 # reverse sign 1203 b result_fs_d 1204 1205/* 1206 * Convert double to single. 1207 */ 1208cvt_s_d: 1209 jal get_fs_dbl 1210 bne t1, DEXP_INF, 1f # is FS an infinity? 1211 li t1, SEXP_INF # convert to single 1212 sll t2, t2, 3 # convert D fraction to S 1213 srl t8, t3, 32 - 3 1214 or t2, t2, t8 1215 b result_fs_s 12161: 1217 bne t1, zero, 2f # is FS zero? 1218 bne t2, zero, 1f 1219 beq t3, zero, result_fs_s # result=0 12201: 1221 jal renorm_fs_d 1222 subu t1, t1, 3 # correct exp for shift below 1223 b 3f 12242: 1225 subu t1, t1, DEXP_BIAS # unbias exponent 1226 or t2, t2, DIMPL_ONE # add implied one bit 12273: 1228 sll t2, t2, 3 # convert D fraction to S 1229 srl t8, t3, 32 - 3 1230 or t2, t2, t8 1231 sll t8, t3, 3 1232 b norm_noshift_s 1233 1234/* 1235 * Convert integer to single. 1236 */ 1237cvt_s_w: 1238 jal get_fs_int 1239 bne t2, zero, 1f # check for zero 1240 move t1, zero 1241 b result_fs_s 1242/* 1243 * Find out how many leading zero bits are in t2 and put in t9. 1244 */ 12451: 1246 move v0, t2 1247 move t9, zero 1248 srl v1, v0, 16 1249 bne v1, zero, 1f 1250 addu t9, 16 1251 sll v0, 16 12521: 1253 srl v1, v0, 24 1254 bne v1, zero, 1f 1255 addu t9, 8 1256 sll v0, 8 12571: 1258 srl v1, v0, 28 1259 bne v1, zero, 1f 1260 addu t9, 4 1261 sll v0, 4 12621: 1263 srl v1, v0, 30 1264 bne v1, zero, 1f 1265 addu t9, 2 1266 sll v0, 2 12671: 1268 srl v1, v0, 31 1269 bne v1, zero, 1f 1270 addu t9, 1 1271/* 1272 * Now shift t2 the correct number of bits. 1273 */ 12741: 1275 subu t9, t9, SLEAD_ZEROS # don't count leading zeros 1276 li t1, 23 # init exponent 1277 subu t1, t1, t9 # compute exponent 1278 beq t9, zero, 1f 1279 li v0, 32 1280 blt t9, zero, 2f # if shift < 0, shift right 1281 subu v0, v0, t9 1282 sll t2, t2, t9 # shift left 12831: 1284 add t1, t1, SEXP_BIAS # bias exponent 1285 and t2, t2, ~SIMPL_ONE # clear implied one bit 1286 b result_fs_s 12872: 1288 negu t9 # shift right by t9 1289 subu v0, v0, t9 1290 sll t8, t2, v0 # save bits shifted out 1291 srl t2, t2, t9 1292 b norm_noshift_s 1293 1294/* 1295 * Convert single to double. 1296 */ 1297cvt_d_s: 1298 jal get_fs_sgl 1299 bne t1, SEXP_INF, 1f # is FS an infinity? 1300 li t1, DEXP_INF # convert to double 1301 b 2f 13021: 1303 bne t1, zero, 2f # is FS denormalized or zero? 1304 beq t2, zero, result_fs_d # is FS zero? 1305 jal renorm_fs_s 1306 move t8, zero 1307 b norm_d 13082: 1309 addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly 1310 sll t3, t2, 32 - 3 # convert S fraction to D 1311 srl t2, t2, 3 1312 b result_fs_d 1313 1314/* 1315 * Convert integer to double. 1316 */ 1317cvt_d_w: 1318 jal get_fs_int 1319 bne t2, zero, 1f # check for zero 1320 move t1, zero # result=0 1321 move t3, zero 1322 b result_fs_d 1323/* 1324 * Find out how many leading zero bits are in t2 and put in t9. 1325 */ 13261: 1327 move v0, t2 1328 move t9, zero 1329 srl v1, v0, 16 1330 bne v1, zero, 1f 1331 addu t9, 16 1332 sll v0, 16 13331: 1334 srl v1, v0, 24 1335 bne v1, zero, 1f 1336 addu t9, 8 1337 sll v0, 8 13381: 1339 srl v1, v0, 28 1340 bne v1, zero, 1f 1341 addu t9, 4 1342 sll v0, 4 13431: 1344 srl v1, v0, 30 1345 bne v1, zero, 1f 1346 addu t9, 2 1347 sll v0, 2 13481: 1349 srl v1, v0, 31 1350 bne v1, zero, 1f 1351 addu t9, 1 1352/* 1353 * Now shift t2 the correct number of bits. 1354 */ 13551: 1356 subu t9, t9, DLEAD_ZEROS # don't count leading zeros 1357 li t1, DEXP_BIAS + 23 # init exponent 1358 subu t1, t1, t9 # compute exponent 1359 beq t9, zero, 1f 1360 li v0, 32 1361 blt t9, zero, 2f # if shift < 0, shift right 1362 subu v0, v0, t9 1363 sll t2, t2, t9 # shift left 13641: 1365 and t2, t2, ~DIMPL_ONE # clear implied one bit 1366 b result_fs_d 13672: 1368 negu t9 # shift right by t9 1369 subu v0, v0, t9 1370 sll t3, t2, v0 1371 srl t2, t2, t9 1372 and t2, t2, ~DIMPL_ONE # clear implied one bit 1373 b result_fs_d 1374 1375/* 1376 * Convert single to integer. 1377 */ 1378cvt_w_s: 1379 jal get_fs_sgl 1380 bne t1, SEXP_INF, 1f # is FS an infinity? 1381 bne t2, zero, invalid_w # invalid conversion 13821: 1383 bne t1, zero, 1f # is FS zero? 1384 beq t2, zero, result_fs_w # result is zero 1385 move t2, zero # result is an inexact zero 1386 b inexact_w 13871: 1388 subu t1, t1, SEXP_BIAS # unbias exponent 1389 or t2, t2, SIMPL_ONE # add implied one bit 1390 sll t3, t2, 32 - 3 # convert S fraction to D 1391 srl t2, t2, 3 1392 b cvt_w 1393 1394/* 1395 * Convert double to integer. 1396 */ 1397cvt_w_d: 1398 jal get_fs_dbl 1399 bne t1, DEXP_INF, 1f # is FS an infinity? 1400 bne t2, zero, invalid_w # invalid conversion 1401 bne t3, zero, invalid_w # invalid conversion 14021: 1403 bne t1, zero, 2f # is FS zero? 1404 bne t2, zero, 1f 1405 beq t3, zero, result_fs_w # result is zero 14061: 1407 move t2, zero # result is an inexact zero 1408 b inexact_w 14092: 1410 subu t1, t1, DEXP_BIAS # unbias exponent 1411 or t2, t2, DIMPL_ONE # add implied one bit 1412cvt_w: 1413 blt t1, WEXP_MIN, underflow_w # is exponent too small? 1414 li v0, WEXP_MAX+1 1415 bgt t1, v0, overflow_w # is exponent too large? 1416 bne t1, v0, 1f # special check for INT_MIN 1417 beq t0, zero, overflow_w # if positive, overflow 1418 bne t2, DIMPL_ONE, overflow_w 1419 bne t3, zero, overflow_w 1420 li t2, INT_MIN # result is INT_MIN 1421 b result_fs_w 14221: 1423 subu v0, t1, 20 # compute amount to shift 1424 beq v0, zero, 2f # is shift needed? 1425 li v1, 32 1426 blt v0, zero, 1f # if shift < 0, shift right 1427 subu v1, v1, v0 # shift left 1428 sll t2, t2, v0 1429 srl t9, t3, v1 # save bits shifted out of t3 1430 or t2, t2, t9 # and put into t2 1431 sll t3, t3, v0 # shift FS's fraction 1432 b 2f 14331: 1434 negu v0 # shift right by v0 1435 subu v1, v1, v0 1436 sll t8, t3, v1 # save bits shifted out 1437 sltu t8, zero, t8 # don't lose any one's 1438 srl t3, t3, v0 # shift FS's fraction 1439 or t3, t3, t8 1440 sll t9, t2, v1 # save bits shifted out of t2 1441 or t3, t3, t9 # and put into t3 1442 srl t2, t2, v0 1443/* 1444 * round result (t0 is sign, t2 is integer part, t3 is fractional part). 1445 */ 14462: 1447 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 1448 beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest 1449 beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) 1450 beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity 1451 beq t0, zero, 5f # if sign is positive, truncate 1452 b 2f 14531: 1454 bne t0, zero, 5f # if sign is negative, truncate 14552: 1456 beq t3, zero, 5f # if no fraction bits, continue 1457 addu t2, t2, 1 # add rounding bit 1458 blt t2, zero, overflow_w # overflow? 1459 b 5f 14603: 1461 li v0, GUARDBIT # load guard bit for rounding 1462 addu v0, v0, t3 # add remainder 1463 sltu v1, v0, t3 # compute carry out 1464 beq v1, zero, 4f # if no carry, continue 1465 addu t2, t2, 1 # add carry to result 1466 blt t2, zero, overflow_w # overflow? 14674: 1468 bne v0, zero, 5f # if rounded remainder is zero 1469 and t2, t2, ~1 # clear LSB (round to nearest) 14705: 1471 beq t0, zero, 1f # result positive? 1472 negu t2 # convert to negative integer 14731: 1474 beq t3, zero, result_fs_w # is result exact? 1475/* 1476 * Handle inexact exception. 1477 */ 1478inexact_w: 1479 or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT 1480 and v0, a1, MACH_FPC_ENABLE_INEXACT 1481 bne v0, zero, fpe_trap 1482 ctc1 a1, MACH_FPC_CSR # save exceptions 1483 b result_fs_w 1484 1485/* 1486 * Conversions to integer which overflow will trap (if enabled), 1487 * or generate an inexact trap (if enabled), 1488 * or generate an invalid exception. 1489 */ 1490overflow_w: 1491 or a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW 1492 and v0, a1, MACH_FPC_ENABLE_OVERFLOW 1493 bne v0, zero, fpe_trap 1494 and v0, a1, MACH_FPC_ENABLE_INEXACT 1495 bne v0, zero, inexact_w # inexact traps enabled? 1496 b invalid_w 1497 1498/* 1499 * Conversions to integer which underflow will trap (if enabled), 1500 * or generate an inexact trap (if enabled), 1501 * or generate an invalid exception. 1502 */ 1503underflow_w: 1504 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 1505 and v0, a1, MACH_FPC_ENABLE_UNDERFLOW 1506 bne v0, zero, fpe_trap 1507 and v0, a1, MACH_FPC_ENABLE_INEXACT 1508 bne v0, zero, inexact_w # inexact traps enabled? 1509 b invalid_w 1510 1511/* 1512 * Compare single. 1513 */ 1514cmp_s: 1515 jal get_fs_sgl 1516 jal get_ft_sgl 1517 bne t1, SEXP_INF, 1f # is FS an infinity? 1518 bne t2, zero, unordered # FS is a NAN 1519 b 2f 15201: 1521 bne t5, SEXP_INF, 2f # is FT an infinity? 1522 bne t6, zero, unordered # FT is a NAN 15232: 1524 sll t1, t1, 23 # reassemble exp & frac 1525 or t1, t1, t2 1526 sll t5, t5, 23 # reassemble exp & frac 1527 or t5, t5, t6 1528 beq t0, zero, 1f # is FS positive? 1529 negu t1 15301: 1531 beq t4, zero, 1f # is FT positive? 1532 negu t5 15331: 1534 li v0, COND_LESS 1535 blt t1, t5, test_cond # is FS < FT? 1536 li v0, COND_EQUAL 1537 beq t1, t5, test_cond # is FS == FT? 1538 move v0, zero # FS > FT 1539 b test_cond 1540 1541/* 1542 * Compare double. 1543 */ 1544cmp_d: 1545 jal get_fs_dbl 1546 jal get_ft_dbl 1547 bne t1, DEXP_INF, 1f # is FS an infinity? 1548 bne t2, zero, unordered 1549 bne t3, zero, unordered # FS is a NAN 1550 b 2f 15511: 1552 bne t5, DEXP_INF, 2f # is FT an infinity? 1553 bne t6, zero, unordered 1554 bne t7, zero, unordered # FT is a NAN 15552: 1556 sll t1, t1, 20 # reassemble exp & frac 1557 or t1, t1, t2 1558 sll t5, t5, 20 # reassemble exp & frac 1559 or t5, t5, t6 1560 beq t0, zero, 1f # is FS positive? 1561 not t3 # negate t1,t3 1562 not t1 1563 addu t3, t3, 1 1564 seq v0, t3, zero # compute carry 1565 addu t1, t1, v0 15661: 1567 beq t4, zero, 1f # is FT positive? 1568 not t7 # negate t5,t7 1569 not t5 1570 addu t7, t7, 1 1571 seq v0, t7, zero # compute carry 1572 addu t5, t5, v0 15731: 1574 li v0, COND_LESS 1575 blt t1, t5, test_cond # is FS(MSW) < FT(MSW)? 1576 move v0, zero 1577 bne t1, t5, test_cond # is FS(MSW) > FT(MSW)? 1578 li v0, COND_LESS 1579 bltu t3, t7, test_cond # is FS(LSW) < FT(LSW)? 1580 li v0, COND_EQUAL 1581 beq t3, t7, test_cond # is FS(LSW) == FT(LSW)? 15821: 1583 move v0, zero # FS > FT 1584 1585test_cond: 1586 and v0, v0, a0 # condition match instruction? 1587 b set_cond 1588unordered: 1589 and v0, a0, COND_SIGNAL 1590 beq v0, zero, 1f # is this a signalling cmp? 1591 or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID 1592 and v0, a1, MACH_FPC_ENABLE_INVALID 1593 bne v0, zero, fpe_trap 15941: 1595 and v0, a0, COND_UNORDERED # this cmp match unordered? 1596set_cond: 1597 bne v0, zero, 1f 1598 and a1, a1, ~MACH_FPC_COND_BIT # clear condition bit 1599 b 2f 16001: 1601 or a1, a1, MACH_FPC_COND_BIT # set condition bit 16022: 1603 ctc1 a1, MACH_FPC_CSR # save condition bit 1604 b done 1605 1606/* 1607 * Determine the amount to shift the fraction in order to restore the 1608 * normalized position. After that, round and handle exceptions. 1609 */ 1610norm_s: 1611 move v0, t2 1612 move t9, zero # t9 = num of leading zeros 1613 bne t2, zero, 1f 1614 move v0, t8 1615 addu t9, 32 16161: 1617 srl v1, v0, 16 1618 bne v1, zero, 1f 1619 addu t9, 16 1620 sll v0, 16 16211: 1622 srl v1, v0, 24 1623 bne v1, zero, 1f 1624 addu t9, 8 1625 sll v0, 8 16261: 1627 srl v1, v0, 28 1628 bne v1, zero, 1f 1629 addu t9, 4 1630 sll v0, 4 16311: 1632 srl v1, v0, 30 1633 bne v1, zero, 1f 1634 addu t9, 2 1635 sll v0, 2 16361: 1637 srl v1, v0, 31 1638 bne v1, zero, 1f 1639 addu t9, 1 1640/* 1641 * Now shift t2,t8 the correct number of bits. 1642 */ 16431: 1644 subu t9, t9, SLEAD_ZEROS # don't count leading zeros 1645 subu t1, t1, t9 # adjust the exponent 1646 beq t9, zero, norm_noshift_s 1647 li v1, 32 1648 blt t9, zero, 1f # if shift < 0, shift right 1649 subu v1, v1, t9 1650 sll t2, t2, t9 # shift t2,t8 left 1651 srl v0, t8, v1 # save bits shifted out 1652 or t2, t2, v0 1653 sll t8, t8, t9 1654 b norm_noshift_s 16551: 1656 negu t9 # shift t2,t8 right by t9 1657 subu v1, v1, t9 1658 sll v0, t8, v1 # save bits shifted out 1659 sltu v0, zero, v0 # be sure to save any one bits 1660 srl t8, t8, t9 1661 or t8, t8, v0 1662 sll v0, t2, v1 # save bits shifted out 1663 or t8, t8, v0 1664 srl t2, t2, t9 1665norm_noshift_s: 1666 move t5, t1 # save unrounded exponent 1667 move t6, t2 # save unrounded fraction 1668 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 1669 beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest 1670 beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) 1671 beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity 1672 beq t0, zero, 5f # if sign is positive, truncate 1673 b 2f 16741: 1675 bne t0, zero, 5f # if sign is negative, truncate 16762: 1677 beq t8, zero, 5f # if exact, continue 1678 addu t2, t2, 1 # add rounding bit 1679 bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent? 1680 addu t1, t1, 1 # adjust exponent 1681 srl t2, t2, 1 # renormalize fraction 1682 b 5f 16833: 1684 li v0, GUARDBIT # load guard bit for rounding 1685 addu v0, v0, t8 # add remainder 1686 sltu v1, v0, t8 # compute carry out 1687 beq v1, zero, 4f # if no carry, continue 1688 addu t2, t2, 1 # add carry to result 1689 bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent? 1690 addu t1, t1, 1 # adjust exponent 1691 srl t2, t2, 1 # renormalize fraction 16924: 1693 bne v0, zero, 5f # if rounded remainder is zero 1694 and t2, t2, ~1 # clear LSB (round to nearest) 16955: 1696 bgt t1, SEXP_MAX, overflow_s # overflow? 1697 blt t1, SEXP_MIN, underflow_s # underflow? 1698 bne t8, zero, inexact_s # is result inexact? 1699 addu t1, t1, SEXP_BIAS # bias exponent 1700 and t2, t2, ~SIMPL_ONE # clear implied one bit 1701 b result_fs_s 1702 1703/* 1704 * Handle inexact exception. 1705 */ 1706inexact_s: 1707 addu t1, t1, SEXP_BIAS # bias exponent 1708 and t2, t2, ~SIMPL_ONE # clear implied one bit 1709inexact_nobias_s: 1710 jal set_fd_sgl # save result 1711 or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT 1712 and v0, a1, MACH_FPC_ENABLE_INEXACT 1713 bne v0, zero, fpe_trap 1714 ctc1 a1, MACH_FPC_CSR # save exceptions 1715 b done 1716 1717/* 1718 * Overflow will trap (if enabled), 1719 * or generate an inexact trap (if enabled), 1720 * or generate an infinity. 1721 */ 1722overflow_s: 1723 or a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW 1724 and v0, a1, MACH_FPC_ENABLE_OVERFLOW 1725 beq v0, zero, 1f 1726 subu t1, t1, 192 # bias exponent 1727 and t2, t2, ~SIMPL_ONE # clear implied one bit 1728 jal set_fd_sgl # save result 1729 b fpe_trap 17301: 1731 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 1732 beq v0, MACH_FPC_ROUND_RN, 5f # round to nearest 1733 beq v0, MACH_FPC_ROUND_RZ, 1f # round to zero (truncate) 1734 beq v0, MACH_FPC_ROUND_RP, 3f # round to +infinity 1735 bne t0, zero, 2f 17361: 1737 li t1, SEXP_MAX # result is max finite 1738 li t2, 0x007fffff 1739 b inexact_s 17402: 1741 li t1, SEXP_MIN - 1 # result is -infinity 1742 move t2, zero 1743 b inexact_s 17443: 1745 bne t0, zero, 1b 17464: 1747 li t1, SEXP_MAX + 1 # result is +infinity 1748 move t2, zero 1749 b inexact_s 17505: 1751 bne t0, zero, 2b 1752 b 4b 1753 1754/* 1755 * In this implementation, "tininess" is detected "after rounding" and 1756 * "loss of accuracy" is detected as "an inexact result". 1757 */ 1758underflow_s: 1759 and v0, a1, MACH_FPC_ENABLE_UNDERFLOW 1760 beq v0, zero, 1f 1761/* 1762 * Underflow is enabled so compute the result and trap. 1763 */ 1764 addu t1, t1, 192 # bias exponent 1765 and t2, t2, ~SIMPL_ONE # clear implied one bit 1766 jal set_fd_sgl # save result 1767 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 1768 b fpe_trap 1769/* 1770 * Underflow is not enabled so compute the result, 1771 * signal inexact result (if it is) and trap (if enabled). 1772 */ 17731: 1774 move t1, t5 # get unrounded exponent 1775 move t2, t6 # get unrounded fraction 1776 li t9, SEXP_MIN # compute shift amount 1777 subu t9, t9, t1 # shift t2,t8 right by t9 1778 blt t9, SFRAC_BITS+2, 1f # shift all the bits out? 1779 move t1, zero # result is inexact zero 1780 move t2, zero 1781 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 1782 b inexact_nobias_s 17831: 1784 li v1, 32 1785 subu v1, v1, t9 1786 sll t8, t2, v1 # save bits shifted out 1787 srl t2, t2, t9 1788/* 1789 * Now round the denormalized result. 1790 */ 1791 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 1792 beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest 1793 beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) 1794 beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity 1795 beq t0, zero, 5f # if sign is positive, truncate 1796 b 2f 17971: 1798 bne t0, zero, 5f # if sign is negative, truncate 17992: 1800 beq t8, zero, 5f # if exact, continue 1801 addu t2, t2, 1 # add rounding bit 1802 b 5f 18033: 1804 li v0, GUARDBIT # load guard bit for rounding 1805 addu v0, v0, t8 # add remainder 1806 sltu v1, v0, t8 # compute carry out 1807 beq v1, zero, 4f # if no carry, continue 1808 addu t2, t2, 1 # add carry to result 18094: 1810 bne v0, zero, 5f # if rounded remainder is zero 1811 and t2, t2, ~1 # clear LSB (round to nearest) 18125: 1813 move t1, zero # denorm or zero exponent 1814 jal set_fd_sgl # save result 1815 beq t8, zero, done # check for exact result 1816 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 1817 or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT 1818 and v0, a1, MACH_FPC_ENABLE_INEXACT 1819 bne v0, zero, fpe_trap 1820 ctc1 a1, MACH_FPC_CSR # save exceptions 1821 b done 1822 1823/* 1824 * Determine the amount to shift the fraction in order to restore the 1825 * normalized position. After that, round and handle exceptions. 1826 */ 1827norm_d: 1828 move v0, t2 1829 move t9, zero # t9 = num of leading zeros 1830 bne t2, zero, 1f 1831 move v0, t3 1832 addu t9, 32 1833 bne t3, zero, 1f 1834 move v0, t8 1835 addu t9, 32 18361: 1837 srl v1, v0, 16 1838 bne v1, zero, 1f 1839 addu t9, 16 1840 sll v0, 16 18411: 1842 srl v1, v0, 24 1843 bne v1, zero, 1f 1844 addu t9, 8 1845 sll v0, 8 18461: 1847 srl v1, v0, 28 1848 bne v1, zero, 1f 1849 addu t9, 4 1850 sll v0, 4 18511: 1852 srl v1, v0, 30 1853 bne v1, zero, 1f 1854 addu t9, 2 1855 sll v0, 2 18561: 1857 srl v1, v0, 31 1858 bne v1, zero, 1f 1859 addu t9, 1 1860/* 1861 * Now shift t2,t3,t8 the correct number of bits. 1862 */ 18631: 1864 subu t9, t9, DLEAD_ZEROS # don't count leading zeros 1865 subu t1, t1, t9 # adjust the exponent 1866 beq t9, zero, norm_noshift_d 1867 li v1, 32 1868 blt t9, zero, 2f # if shift < 0, shift right 1869 blt t9, v1, 1f # shift by < 32? 1870 subu t9, t9, v1 # shift by >= 32 1871 subu v1, v1, t9 1872 sll t2, t3, t9 # shift left by t9 1873 srl v0, t8, v1 # save bits shifted out 1874 or t2, t2, v0 1875 sll t3, t8, t9 1876 move t8, zero 1877 b norm_noshift_d 18781: 1879 subu v1, v1, t9 1880 sll t2, t2, t9 # shift left by t9 1881 srl v0, t3, v1 # save bits shifted out 1882 or t2, t2, v0 1883 sll t3, t3, t9 1884 srl v0, t8, v1 # save bits shifted out 1885 or t3, t3, v0 1886 sll t8, t8, t9 1887 b norm_noshift_d 18882: 1889 negu t9 # shift right by t9 1890 subu v1, v1, t9 # (known to be < 32 bits) 1891 sll v0, t8, v1 # save bits shifted out 1892 sltu v0, zero, v0 # be sure to save any one bits 1893 srl t8, t8, t9 1894 or t8, t8, v0 1895 sll v0, t3, v1 # save bits shifted out 1896 or t8, t8, v0 1897 srl t3, t3, t9 1898 sll v0, t2, v1 # save bits shifted out 1899 or t3, t3, v0 1900 srl t2, t2, t9 1901norm_noshift_d: 1902 move t5, t1 # save unrounded exponent 1903 move t6, t2 # save unrounded fraction (MS) 1904 move t7, t3 # save unrounded fraction (LS) 1905 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 1906 beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest 1907 beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) 1908 beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity 1909 beq t0, zero, 5f # if sign is positive, truncate 1910 b 2f 19111: 1912 bne t0, zero, 5f # if sign is negative, truncate 19132: 1914 beq t8, zero, 5f # if exact, continue 1915 addu t3, t3, 1 # add rounding bit 1916 bne t3, zero, 5f # branch if no carry 1917 addu t2, t2, 1 # add carry 1918 bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent? 1919 addu t1, t1, 1 # adjust exponent 1920 srl t2, t2, 1 # renormalize fraction 1921 b 5f 19223: 1923 li v0, GUARDBIT # load guard bit for rounding 1924 addu v0, v0, t8 # add remainder 1925 sltu v1, v0, t8 # compute carry out 1926 beq v1, zero, 4f # branch if no carry 1927 addu t3, t3, 1 # add carry 1928 bne t3, zero, 4f # branch if no carry 1929 addu t2, t2, 1 # add carry to result 1930 bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent? 1931 addu t1, t1, 1 # adjust exponent 1932 srl t2, t2, 1 # renormalize fraction 19334: 1934 bne v0, zero, 5f # if rounded remainder is zero 1935 and t3, t3, ~1 # clear LSB (round to nearest) 19365: 1937 bgt t1, DEXP_MAX, overflow_d # overflow? 1938 blt t1, DEXP_MIN, underflow_d # underflow? 1939 bne t8, zero, inexact_d # is result inexact? 1940 addu t1, t1, DEXP_BIAS # bias exponent 1941 and t2, t2, ~DIMPL_ONE # clear implied one bit 1942 b result_fs_d 1943 1944/* 1945 * Handle inexact exception. 1946 */ 1947inexact_d: 1948 addu t1, t1, DEXP_BIAS # bias exponent 1949 and t2, t2, ~DIMPL_ONE # clear implied one bit 1950inexact_nobias_d: 1951 jal set_fd_dbl # save result 1952 or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT 1953 and v0, a1, MACH_FPC_ENABLE_INEXACT 1954 bne v0, zero, fpe_trap 1955 ctc1 a1, MACH_FPC_CSR # save exceptions 1956 b done 1957 1958/* 1959 * Overflow will trap (if enabled), 1960 * or generate an inexact trap (if enabled), 1961 * or generate an infinity. 1962 */ 1963overflow_d: 1964 or a1, a1, MACH_FPC_EXCEPTION_OVERFLOW | MACH_FPC_STICKY_OVERFLOW 1965 and v0, a1, MACH_FPC_ENABLE_OVERFLOW 1966 beq v0, zero, 1f 1967 subu t1, t1, 1536 # bias exponent 1968 and t2, t2, ~DIMPL_ONE # clear implied one bit 1969 jal set_fd_dbl # save result 1970 b fpe_trap 19711: 1972 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 1973 beq v0, MACH_FPC_ROUND_RN, 5f # round to nearest 1974 beq v0, MACH_FPC_ROUND_RZ, 1f # round to zero (truncate) 1975 beq v0, MACH_FPC_ROUND_RP, 3f # round to +infinity 1976 bne t0, zero, 2f 19771: 1978 li t1, DEXP_MAX # result is max finite 1979 li t2, 0x000fffff 1980 li t3, 0xffffffff 1981 b inexact_d 19822: 1983 li t1, DEXP_MIN - 1 # result is -infinity 1984 move t2, zero 1985 move t3, zero 1986 b inexact_d 19873: 1988 bne t0, zero, 1b 19894: 1990 li t1, DEXP_MAX + 1 # result is +infinity 1991 move t2, zero 1992 move t3, zero 1993 b inexact_d 19945: 1995 bne t0, zero, 2b 1996 b 4b 1997 1998/* 1999 * In this implementation, "tininess" is detected "after rounding" and 2000 * "loss of accuracy" is detected as "an inexact result". 2001 */ 2002underflow_d: 2003 and v0, a1, MACH_FPC_ENABLE_UNDERFLOW 2004 beq v0, zero, 1f 2005/* 2006 * Underflow is enabled so compute the result and trap. 2007 */ 2008 addu t1, t1, 1536 # bias exponent 2009 and t2, t2, ~DIMPL_ONE # clear implied one bit 2010 jal set_fd_dbl # save result 2011 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 2012 b fpe_trap 2013/* 2014 * Underflow is not enabled so compute the result, 2015 * signal inexact result (if it is) and trap (if enabled). 2016 */ 20171: 2018 move t1, t5 # get unrounded exponent 2019 move t2, t6 # get unrounded fraction (MS) 2020 move t3, t7 # get unrounded fraction (LS) 2021 li t9, DEXP_MIN # compute shift amount 2022 subu t9, t9, t1 # shift t2,t8 right by t9 2023 blt t9, DFRAC_BITS+2, 1f # shift all the bits out? 2024 move t1, zero # result is inexact zero 2025 move t2, zero 2026 move t3, zero 2027 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 2028 b inexact_nobias_d 20291: 2030 li v1, 32 2031 blt t9, v1, 1f # shift by < 32? 2032 subu t9, t9, v1 # shift right by >= 32 2033 subu v1, v1, t9 2034 sll t8, t2, v1 # save bits shifted out 2035 srl t3, t2, t9 2036 move t2, zero 2037 b 2f 20381: 2039 subu v1, v1, t9 # shift right by t9 2040 sll t8, t3, v1 # save bits shifted out 2041 srl t3, t3, t9 2042 sll v0, t2, v1 # save bits shifted out 2043 or t3, t3, v0 2044 srl t2, t2, t9 2045/* 2046 * Now round the denormalized result. 2047 */ 20482: 2049 and v0, a1, MACH_FPC_ROUNDING_BITS # get rounding mode 2050 beq v0, MACH_FPC_ROUND_RN, 3f # round to nearest 2051 beq v0, MACH_FPC_ROUND_RZ, 5f # round to zero (truncate) 2052 beq v0, MACH_FPC_ROUND_RP, 1f # round to +infinity 2053 beq t0, zero, 5f # if sign is positive, truncate 2054 b 2f 20551: 2056 bne t0, zero, 5f # if sign is negative, truncate 20572: 2058 beq t8, zero, 5f # if exact, continue 2059 addu t3, t3, 1 # add rounding bit 2060 bne t3, zero, 5f # if no carry, continue 2061 addu t2, t2, 1 # add carry 2062 b 5f 20633: 2064 li v0, GUARDBIT # load guard bit for rounding 2065 addu v0, v0, t8 # add remainder 2066 sltu v1, v0, t8 # compute carry out 2067 beq v1, zero, 4f # if no carry, continue 2068 addu t3, t3, 1 # add rounding bit 2069 bne t3, zero, 4f # if no carry, continue 2070 addu t2, t2, 1 # add carry 20714: 2072 bne v0, zero, 5f # if rounded remainder is zero 2073 and t3, t3, ~1 # clear LSB (round to nearest) 20745: 2075 move t1, zero # denorm or zero exponent 2076 jal set_fd_dbl # save result 2077 beq t8, zero, done # check for exact result 2078 or a1, a1, MACH_FPC_EXCEPTION_UNDERFLOW | MACH_FPC_STICKY_UNDERFLOW 2079 or a1, a1, MACH_FPC_EXCEPTION_INEXACT | MACH_FPC_STICKY_INEXACT 2080 and v0, a1, MACH_FPC_ENABLE_INEXACT 2081 bne v0, zero, fpe_trap 2082 ctc1 a1, MACH_FPC_CSR # save exceptions 2083 b done 2084 2085/* 2086 * Signal an invalid operation if the trap is enabled; otherwise, 2087 * the result is a quiet NAN. 2088 */ 2089invalid_s: # trap invalid operation 2090 or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID 2091 and v0, a1, MACH_FPC_ENABLE_INVALID 2092 bne v0, zero, fpe_trap 2093 ctc1 a1, MACH_FPC_CSR # save exceptions 2094 move t0, zero # result is a quiet NAN 2095 li t1, SEXP_INF 2096 li t2, SQUIET_NAN 2097 jal set_fd_sgl # save result (in t0,t1,t2) 2098 b done 2099 2100/* 2101 * Signal an invalid operation if the trap is enabled; otherwise, 2102 * the result is a quiet NAN. 2103 */ 2104invalid_d: # trap invalid operation 2105 or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID 2106 and v0, a1, MACH_FPC_ENABLE_INVALID 2107 bne v0, zero, fpe_trap 2108 ctc1 a1, MACH_FPC_CSR # save exceptions 2109 move t0, zero # result is a quiet NAN 2110 li t1, DEXP_INF 2111 li t2, DQUIET_NAN0 2112 li t3, DQUIET_NAN1 2113 jal set_fd_dbl # save result (in t0,t1,t2,t3) 2114 b done 2115 2116/* 2117 * Signal an invalid operation if the trap is enabled; otherwise, 2118 * the result is INT_MAX or INT_MIN. 2119 */ 2120invalid_w: # trap invalid operation 2121 or a1, a1, MACH_FPC_EXCEPTION_INVALID | MACH_FPC_STICKY_INVALID 2122 and v0, a1, MACH_FPC_ENABLE_INVALID 2123 bne v0, zero, fpe_trap 2124 ctc1 a1, MACH_FPC_CSR # save exceptions 2125 bne t0, zero, 1f 2126 li t2, INT_MAX # result is INT_MAX 2127 b result_fs_w 21281: 2129 li t2, INT_MIN # result is INT_MIN 2130 b result_fs_w 2131 2132/* 2133 * Trap if the hardware should have handled this case. 2134 */ 2135fpe_trap: 2136 move a2, a1 # code = FP CSR 2137 ctc1 a1, MACH_FPC_CSR # save exceptions 2138 lw a0, curproc # get current process 2139 li a1, SIGFPE 2140 jal trapsignal 2141 b done 2142 2143/* 2144 * Send an illegal instruction signal to the current process. 2145 */ 2146ill: 2147 ctc1 a1, MACH_FPC_CSR # save exceptions 2148 move a2, a0 # code = FP instruction 2149 lw a0, curproc # get current process 2150 li a1, SIGILL 2151 jal trapsignal 2152 b done 2153 2154result_ft_s: 2155 move t0, t4 # result is FT 2156 move t1, t5 2157 move t2, t6 2158result_fs_s: # result is FS 2159 jal set_fd_sgl # save result (in t0,t1,t2) 2160 b done 2161 2162result_fs_w: 2163 jal set_fd_word # save result (in t2) 2164 b done 2165 2166result_ft_d: 2167 move t0, t4 # result is FT 2168 move t1, t5 2169 move t2, t6 2170 move t3, t7 2171result_fs_d: # result is FS 2172 jal set_fd_dbl # save result (in t0,t1,t2,t3) 2173 2174done: 2175 lw ra, STAND_RA_OFFSET(sp) 2176 addu sp, sp, STAND_FRAME_SIZE 2177 j ra 2178END(MachEmulateFP) 2179 2180/*---------------------------------------------------------------------------- 2181 * get_fs_sgl -- 2182 * 2183 * Read (single precision) the FS register (bits 15-11) and 2184 * break up into fields. 2185 * This is an internal routine used by MachEmulateFP only. 2186 * 2187 * Results: 2188 * t0 contains the sign 2189 * t1 contains the (biased) exponent 2190 * t2 contains the fraction 2191 * 2192 *---------------------------------------------------------------------------- 2193 */ 2194LEAF(get_fs_sgl) 2195 srl a3, a0, 12 - 2 # get FS field (even regs only) 2196 and a3, a3, 0xF << 2 # mask FS field 2197 lw a3, get_fs_sgl_tbl(a3) # switch on register number 2198 j a3 2199 2200 .rdata 2201get_fs_sgl_tbl: 2202 .word get_fs_sgl_f0 2203 .word get_fs_sgl_f2 2204 .word get_fs_sgl_f4 2205 .word get_fs_sgl_f6 2206 .word get_fs_sgl_f8 2207 .word get_fs_sgl_f10 2208 .word get_fs_sgl_f12 2209 .word get_fs_sgl_f14 2210 .word get_fs_sgl_f16 2211 .word get_fs_sgl_f18 2212 .word get_fs_sgl_f20 2213 .word get_fs_sgl_f22 2214 .word get_fs_sgl_f24 2215 .word get_fs_sgl_f26 2216 .word get_fs_sgl_f28 2217 .word get_fs_sgl_f30 2218 .text 2219 2220get_fs_sgl_f0: 2221 mfc1 t0, $f0 2222 b get_fs_sgl_done 2223get_fs_sgl_f2: 2224 mfc1 t0, $f2 2225 b get_fs_sgl_done 2226get_fs_sgl_f4: 2227 mfc1 t0, $f4 2228 b get_fs_sgl_done 2229get_fs_sgl_f6: 2230 mfc1 t0, $f6 2231 b get_fs_sgl_done 2232get_fs_sgl_f8: 2233 mfc1 t0, $f8 2234 b get_fs_sgl_done 2235get_fs_sgl_f10: 2236 mfc1 t0, $f10 2237 b get_fs_sgl_done 2238get_fs_sgl_f12: 2239 mfc1 t0, $f12 2240 b get_fs_sgl_done 2241get_fs_sgl_f14: 2242 mfc1 t0, $f14 2243 b get_fs_sgl_done 2244get_fs_sgl_f16: 2245 mfc1 t0, $f16 2246 b get_fs_sgl_done 2247get_fs_sgl_f18: 2248 mfc1 t0, $f18 2249 b get_fs_sgl_done 2250get_fs_sgl_f20: 2251 mfc1 t0, $f20 2252 b get_fs_sgl_done 2253get_fs_sgl_f22: 2254 mfc1 t0, $f22 2255 b get_fs_sgl_done 2256get_fs_sgl_f24: 2257 mfc1 t0, $f24 2258 b get_fs_sgl_done 2259get_fs_sgl_f26: 2260 mfc1 t0, $f26 2261 b get_fs_sgl_done 2262get_fs_sgl_f28: 2263 mfc1 t0, $f28 2264 b get_fs_sgl_done 2265get_fs_sgl_f30: 2266 mfc1 t0, $f30 2267get_fs_sgl_done: 2268 srl t1, t0, 23 # get exponent 2269 and t1, t1, 0xFF 2270 and t2, t0, 0x7FFFFF # get fraction 2271 srl t0, t0, 31 # get sign 2272 bne t1, SEXP_INF, 1f # is it a signalling NAN? 2273 and v0, t2, SSIGNAL_NAN 2274 bne v0, zero, invalid_s 22751: 2276 j ra 2277END(get_fs_sgl) 2278 2279/*---------------------------------------------------------------------------- 2280 * get_fs_dbl -- 2281 * 2282 * Read (double precision) the FS register (bits 15-11) and 2283 * break up into fields. 2284 * This is an internal routine used by MachEmulateFP only. 2285 * 2286 * Results: 2287 * t0 contains the sign 2288 * t1 contains the (biased) exponent 2289 * t2 contains the fraction 2290 * t3 contains the remaining fraction 2291 * 2292 *---------------------------------------------------------------------------- 2293 */ 2294LEAF(get_fs_dbl) 2295 srl a3, a0, 12 - 2 # get FS field (even regs only) 2296 and a3, a3, 0xF << 2 # mask FS field 2297 lw a3, get_fs_dbl_tbl(a3) # switch on register number 2298 j a3 2299 2300 .rdata 2301get_fs_dbl_tbl: 2302 .word get_fs_dbl_f0 2303 .word get_fs_dbl_f2 2304 .word get_fs_dbl_f4 2305 .word get_fs_dbl_f6 2306 .word get_fs_dbl_f8 2307 .word get_fs_dbl_f10 2308 .word get_fs_dbl_f12 2309 .word get_fs_dbl_f14 2310 .word get_fs_dbl_f16 2311 .word get_fs_dbl_f18 2312 .word get_fs_dbl_f20 2313 .word get_fs_dbl_f22 2314 .word get_fs_dbl_f24 2315 .word get_fs_dbl_f26 2316 .word get_fs_dbl_f28 2317 .word get_fs_dbl_f30 2318 .text 2319 2320get_fs_dbl_f0: 2321 mfc1 t3, $f0 2322 mfc1 t0, $f1 2323 b get_fs_dbl_done 2324get_fs_dbl_f2: 2325 mfc1 t3, $f2 2326 mfc1 t0, $f3 2327 b get_fs_dbl_done 2328get_fs_dbl_f4: 2329 mfc1 t3, $f4 2330 mfc1 t0, $f5 2331 b get_fs_dbl_done 2332get_fs_dbl_f6: 2333 mfc1 t3, $f6 2334 mfc1 t0, $f7 2335 b get_fs_dbl_done 2336get_fs_dbl_f8: 2337 mfc1 t3, $f8 2338 mfc1 t0, $f9 2339 b get_fs_dbl_done 2340get_fs_dbl_f10: 2341 mfc1 t3, $f10 2342 mfc1 t0, $f11 2343 b get_fs_dbl_done 2344get_fs_dbl_f12: 2345 mfc1 t3, $f12 2346 mfc1 t0, $f13 2347 b get_fs_dbl_done 2348get_fs_dbl_f14: 2349 mfc1 t3, $f14 2350 mfc1 t0, $f15 2351 b get_fs_dbl_done 2352get_fs_dbl_f16: 2353 mfc1 t3, $f16 2354 mfc1 t0, $f17 2355 b get_fs_dbl_done 2356get_fs_dbl_f18: 2357 mfc1 t3, $f18 2358 mfc1 t0, $f19 2359 b get_fs_dbl_done 2360get_fs_dbl_f20: 2361 mfc1 t3, $f20 2362 mfc1 t0, $f21 2363 b get_fs_dbl_done 2364get_fs_dbl_f22: 2365 mfc1 t3, $f22 2366 mfc1 t0, $f23 2367 b get_fs_dbl_done 2368get_fs_dbl_f24: 2369 mfc1 t3, $f24 2370 mfc1 t0, $f25 2371 b get_fs_dbl_done 2372get_fs_dbl_f26: 2373 mfc1 t3, $f26 2374 mfc1 t0, $f27 2375 b get_fs_dbl_done 2376get_fs_dbl_f28: 2377 mfc1 t3, $f28 2378 mfc1 t0, $f29 2379 b get_fs_dbl_done 2380get_fs_dbl_f30: 2381 mfc1 t3, $f30 2382 mfc1 t0, $f31 2383get_fs_dbl_done: 2384 srl t1, t0, 20 # get exponent 2385 and t1, t1, 0x7FF 2386 and t2, t0, 0xFFFFF # get fraction 2387 srl t0, t0, 31 # get sign 2388 bne t1, DEXP_INF, 1f # is it a signalling NAN? 2389 and v0, t2, DSIGNAL_NAN 2390 bne v0, zero, invalid_d 23911: 2392 j ra 2393END(get_fs_dbl) 2394 2395/*---------------------------------------------------------------------------- 2396 * get_fs_int -- 2397 * 2398 * Read (integer) the FS register (bits 15-11). 2399 * This is an internal routine used by MachEmulateFP only. 2400 * 2401 * Results: 2402 * t0 contains the sign 2403 * t2 contains the fraction 2404 * 2405 *---------------------------------------------------------------------------- 2406 */ 2407LEAF(get_fs_int) 2408 srl a3, a0, 12 - 2 # get FS field (even regs only) 2409 and a3, a3, 0xF << 2 # mask FS field 2410 lw a3, get_fs_int_tbl(a3) # switch on register number 2411 j a3 2412 2413 .rdata 2414get_fs_int_tbl: 2415 .word get_fs_int_f0 2416 .word get_fs_int_f2 2417 .word get_fs_int_f4 2418 .word get_fs_int_f6 2419 .word get_fs_int_f8 2420 .word get_fs_int_f10 2421 .word get_fs_int_f12 2422 .word get_fs_int_f14 2423 .word get_fs_int_f16 2424 .word get_fs_int_f18 2425 .word get_fs_int_f20 2426 .word get_fs_int_f22 2427 .word get_fs_int_f24 2428 .word get_fs_int_f26 2429 .word get_fs_int_f28 2430 .word get_fs_int_f30 2431 .text 2432 2433get_fs_int_f0: 2434 mfc1 t2, $f0 2435 b get_fs_int_done 2436get_fs_int_f2: 2437 mfc1 t2, $f2 2438 b get_fs_int_done 2439get_fs_int_f4: 2440 mfc1 t2, $f4 2441 b get_fs_int_done 2442get_fs_int_f6: 2443 mfc1 t2, $f6 2444 b get_fs_int_done 2445get_fs_int_f8: 2446 mfc1 t2, $f8 2447 b get_fs_int_done 2448get_fs_int_f10: 2449 mfc1 t2, $f10 2450 b get_fs_int_done 2451get_fs_int_f12: 2452 mfc1 t2, $f12 2453 b get_fs_int_done 2454get_fs_int_f14: 2455 mfc1 t2, $f14 2456 b get_fs_int_done 2457get_fs_int_f16: 2458 mfc1 t2, $f16 2459 b get_fs_int_done 2460get_fs_int_f18: 2461 mfc1 t2, $f18 2462 b get_fs_int_done 2463get_fs_int_f20: 2464 mfc1 t2, $f20 2465 b get_fs_int_done 2466get_fs_int_f22: 2467 mfc1 t2, $f22 2468 b get_fs_int_done 2469get_fs_int_f24: 2470 mfc1 t2, $f24 2471 b get_fs_int_done 2472get_fs_int_f26: 2473 mfc1 t2, $f26 2474 b get_fs_int_done 2475get_fs_int_f28: 2476 mfc1 t2, $f28 2477 b get_fs_int_done 2478get_fs_int_f30: 2479 mfc1 t2, $f30 2480get_fs_int_done: 2481 srl t0, t2, 31 # init the sign bit 2482 bge t2, zero, 1f 2483 negu t2 24841: 2485 j ra 2486END(get_fs_int) 2487 2488/*---------------------------------------------------------------------------- 2489 * get_ft_sgl -- 2490 * 2491 * Read (single precision) the FT register (bits 20-16) and 2492 * break up into fields. 2493 * This is an internal routine used by MachEmulateFP only. 2494 * 2495 * Results: 2496 * t4 contains the sign 2497 * t5 contains the (biased) exponent 2498 * t6 contains the fraction 2499 * 2500 *---------------------------------------------------------------------------- 2501 */ 2502LEAF(get_ft_sgl) 2503 srl a3, a0, 17 - 2 # get FT field (even regs only) 2504 and a3, a3, 0xF << 2 # mask FT field 2505 lw a3, get_ft_sgl_tbl(a3) # switch on register number 2506 j a3 2507 2508 .rdata 2509get_ft_sgl_tbl: 2510 .word get_ft_sgl_f0 2511 .word get_ft_sgl_f2 2512 .word get_ft_sgl_f4 2513 .word get_ft_sgl_f6 2514 .word get_ft_sgl_f8 2515 .word get_ft_sgl_f10 2516 .word get_ft_sgl_f12 2517 .word get_ft_sgl_f14 2518 .word get_ft_sgl_f16 2519 .word get_ft_sgl_f18 2520 .word get_ft_sgl_f20 2521 .word get_ft_sgl_f22 2522 .word get_ft_sgl_f24 2523 .word get_ft_sgl_f26 2524 .word get_ft_sgl_f28 2525 .word get_ft_sgl_f30 2526 .text 2527 2528get_ft_sgl_f0: 2529 mfc1 t4, $f0 2530 b get_ft_sgl_done 2531get_ft_sgl_f2: 2532 mfc1 t4, $f2 2533 b get_ft_sgl_done 2534get_ft_sgl_f4: 2535 mfc1 t4, $f4 2536 b get_ft_sgl_done 2537get_ft_sgl_f6: 2538 mfc1 t4, $f6 2539 b get_ft_sgl_done 2540get_ft_sgl_f8: 2541 mfc1 t4, $f8 2542 b get_ft_sgl_done 2543get_ft_sgl_f10: 2544 mfc1 t4, $f10 2545 b get_ft_sgl_done 2546get_ft_sgl_f12: 2547 mfc1 t4, $f12 2548 b get_ft_sgl_done 2549get_ft_sgl_f14: 2550 mfc1 t4, $f14 2551 b get_ft_sgl_done 2552get_ft_sgl_f16: 2553 mfc1 t4, $f16 2554 b get_ft_sgl_done 2555get_ft_sgl_f18: 2556 mfc1 t4, $f18 2557 b get_ft_sgl_done 2558get_ft_sgl_f20: 2559 mfc1 t4, $f20 2560 b get_ft_sgl_done 2561get_ft_sgl_f22: 2562 mfc1 t4, $f22 2563 b get_ft_sgl_done 2564get_ft_sgl_f24: 2565 mfc1 t4, $f24 2566 b get_ft_sgl_done 2567get_ft_sgl_f26: 2568 mfc1 t4, $f26 2569 b get_ft_sgl_done 2570get_ft_sgl_f28: 2571 mfc1 t4, $f28 2572 b get_ft_sgl_done 2573get_ft_sgl_f30: 2574 mfc1 t4, $f30 2575get_ft_sgl_done: 2576 srl t5, t4, 23 # get exponent 2577 and t5, t5, 0xFF 2578 and t6, t4, 0x7FFFFF # get fraction 2579 srl t4, t4, 31 # get sign 2580 bne t5, SEXP_INF, 1f # is it a signalling NAN? 2581 and v0, t6, SSIGNAL_NAN 2582 bne v0, zero, invalid_s 25831: 2584 j ra 2585END(get_ft_sgl) 2586 2587/*---------------------------------------------------------------------------- 2588 * get_ft_dbl -- 2589 * 2590 * Read (double precision) the FT register (bits 20-16) and 2591 * break up into fields. 2592 * This is an internal routine used by MachEmulateFP only. 2593 * 2594 * Results: 2595 * t4 contains the sign 2596 * t5 contains the (biased) exponent 2597 * t6 contains the fraction 2598 * t7 contains the remaining fraction 2599 * 2600 *---------------------------------------------------------------------------- 2601 */ 2602LEAF(get_ft_dbl) 2603 srl a3, a0, 17 - 2 # get FT field (even regs only) 2604 and a3, a3, 0xF << 2 # mask FT field 2605 lw a3, get_ft_dbl_tbl(a3) # switch on register number 2606 j a3 2607 2608 .rdata 2609get_ft_dbl_tbl: 2610 .word get_ft_dbl_f0 2611 .word get_ft_dbl_f2 2612 .word get_ft_dbl_f4 2613 .word get_ft_dbl_f6 2614 .word get_ft_dbl_f8 2615 .word get_ft_dbl_f10 2616 .word get_ft_dbl_f12 2617 .word get_ft_dbl_f14 2618 .word get_ft_dbl_f16 2619 .word get_ft_dbl_f18 2620 .word get_ft_dbl_f20 2621 .word get_ft_dbl_f22 2622 .word get_ft_dbl_f24 2623 .word get_ft_dbl_f26 2624 .word get_ft_dbl_f28 2625 .word get_ft_dbl_f30 2626 .text 2627 2628get_ft_dbl_f0: 2629 mfc1 t7, $f0 2630 mfc1 t4, $f1 2631 b get_ft_dbl_done 2632get_ft_dbl_f2: 2633 mfc1 t7, $f2 2634 mfc1 t4, $f3 2635 b get_ft_dbl_done 2636get_ft_dbl_f4: 2637 mfc1 t7, $f4 2638 mfc1 t4, $f5 2639 b get_ft_dbl_done 2640get_ft_dbl_f6: 2641 mfc1 t7, $f6 2642 mfc1 t4, $f7 2643 b get_ft_dbl_done 2644get_ft_dbl_f8: 2645 mfc1 t7, $f8 2646 mfc1 t4, $f9 2647 b get_ft_dbl_done 2648get_ft_dbl_f10: 2649 mfc1 t7, $f10 2650 mfc1 t4, $f11 2651 b get_ft_dbl_done 2652get_ft_dbl_f12: 2653 mfc1 t7, $f12 2654 mfc1 t4, $f13 2655 b get_ft_dbl_done 2656get_ft_dbl_f14: 2657 mfc1 t7, $f14 2658 mfc1 t4, $f15 2659 b get_ft_dbl_done 2660get_ft_dbl_f16: 2661 mfc1 t7, $f16 2662 mfc1 t4, $f17 2663 b get_ft_dbl_done 2664get_ft_dbl_f18: 2665 mfc1 t7, $f18 2666 mfc1 t4, $f19 2667 b get_ft_dbl_done 2668get_ft_dbl_f20: 2669 mfc1 t7, $f20 2670 mfc1 t4, $f21 2671 b get_ft_dbl_done 2672get_ft_dbl_f22: 2673 mfc1 t7, $f22 2674 mfc1 t4, $f23 2675 b get_ft_dbl_done 2676get_ft_dbl_f24: 2677 mfc1 t7, $f24 2678 mfc1 t4, $f25 2679 b get_ft_dbl_done 2680get_ft_dbl_f26: 2681 mfc1 t7, $f26 2682 mfc1 t4, $f27 2683 b get_ft_dbl_done 2684get_ft_dbl_f28: 2685 mfc1 t7, $f28 2686 mfc1 t4, $f29 2687 b get_ft_dbl_done 2688get_ft_dbl_f30: 2689 mfc1 t7, $f30 2690 mfc1 t4, $f31 2691get_ft_dbl_done: 2692 srl t5, t4, 20 # get exponent 2693 and t5, t5, 0x7FF 2694 and t6, t4, 0xFFFFF # get fraction 2695 srl t4, t4, 31 # get sign 2696 bne t5, DEXP_INF, 1f # is it a signalling NAN? 2697 and v0, t6, DSIGNAL_NAN 2698 bne v0, zero, invalid_d 26991: 2700 j ra 2701END(get_ft_dbl) 2702 2703/*---------------------------------------------------------------------------- 2704 * set_fd_sgl -- 2705 * 2706 * Write (single precision) the FD register (bits 10-6). 2707 * This is an internal routine used by MachEmulateFP only. 2708 * 2709 * Arguments: 2710 * a0 contains the FP instruction 2711 * t0 contains the sign 2712 * t1 contains the (biased) exponent 2713 * t2 contains the fraction 2714 * 2715 * set_fd_word -- 2716 * 2717 * Write (integer) the FD register (bits 10-6). 2718 * This is an internal routine used by MachEmulateFP only. 2719 * 2720 * Arguments: 2721 * a0 contains the FP instruction 2722 * t2 contains the integer 2723 * 2724 *---------------------------------------------------------------------------- 2725 */ 2726LEAF(set_fd_sgl) 2727 sll t0, t0, 31 # position sign 2728 sll t1, t1, 23 # position exponent 2729 or t2, t2, t0 2730 or t2, t2, t1 2731ALEAF(set_fd_word) 2732 srl a3, a0, 7 - 2 # get FD field (even regs only) 2733 and a3, a3, 0xF << 2 # mask FT field 2734 lw a3, set_fd_sgl_tbl(a3) # switch on register number 2735 j a3 2736 2737 .rdata 2738set_fd_sgl_tbl: 2739 .word set_fd_sgl_f0 2740 .word set_fd_sgl_f2 2741 .word set_fd_sgl_f4 2742 .word set_fd_sgl_f6 2743 .word set_fd_sgl_f8 2744 .word set_fd_sgl_f10 2745 .word set_fd_sgl_f12 2746 .word set_fd_sgl_f14 2747 .word set_fd_sgl_f16 2748 .word set_fd_sgl_f18 2749 .word set_fd_sgl_f20 2750 .word set_fd_sgl_f22 2751 .word set_fd_sgl_f24 2752 .word set_fd_sgl_f26 2753 .word set_fd_sgl_f28 2754 .word set_fd_sgl_f30 2755 .text 2756 2757set_fd_sgl_f0: 2758 mtc1 t2, $f0 2759 j ra 2760set_fd_sgl_f2: 2761 mtc1 t2, $f2 2762 j ra 2763set_fd_sgl_f4: 2764 mtc1 t2, $f4 2765 j ra 2766set_fd_sgl_f6: 2767 mtc1 t2, $f6 2768 j ra 2769set_fd_sgl_f8: 2770 mtc1 t2, $f8 2771 j ra 2772set_fd_sgl_f10: 2773 mtc1 t2, $f10 2774 j ra 2775set_fd_sgl_f12: 2776 mtc1 t2, $f12 2777 j ra 2778set_fd_sgl_f14: 2779 mtc1 t2, $f14 2780 j ra 2781set_fd_sgl_f16: 2782 mtc1 t2, $f16 2783 j ra 2784set_fd_sgl_f18: 2785 mtc1 t2, $f18 2786 j ra 2787set_fd_sgl_f20: 2788 mtc1 t2, $f20 2789 j ra 2790set_fd_sgl_f22: 2791 mtc1 t2, $f22 2792 j ra 2793set_fd_sgl_f24: 2794 mtc1 t2, $f24 2795 j ra 2796set_fd_sgl_f26: 2797 mtc1 t2, $f26 2798 j ra 2799set_fd_sgl_f28: 2800 mtc1 t2, $f28 2801 j ra 2802set_fd_sgl_f30: 2803 mtc1 t2, $f30 2804 j ra 2805END(set_fd_sgl) 2806 2807/*---------------------------------------------------------------------------- 2808 * set_fd_dbl -- 2809 * 2810 * Write (double precision) the FT register (bits 10-6). 2811 * This is an internal routine used by MachEmulateFP only. 2812 * 2813 * Arguments: 2814 * a0 contains the FP instruction 2815 * t0 contains the sign 2816 * t1 contains the (biased) exponent 2817 * t2 contains the fraction 2818 * t3 contains the remaining fraction 2819 * 2820 *---------------------------------------------------------------------------- 2821 */ 2822LEAF(set_fd_dbl) 2823 sll t0, t0, 31 # set sign 2824 sll t1, t1, 20 # set exponent 2825 or t0, t0, t1 2826 or t0, t0, t2 # set fraction 2827 srl a3, a0, 7 - 2 # get FD field (even regs only) 2828 and a3, a3, 0xF << 2 # mask FD field 2829 lw a3, set_fd_dbl_tbl(a3) # switch on register number 2830 j a3 2831 2832 .rdata 2833set_fd_dbl_tbl: 2834 .word set_fd_dbl_f0 2835 .word set_fd_dbl_f2 2836 .word set_fd_dbl_f4 2837 .word set_fd_dbl_f6 2838 .word set_fd_dbl_f8 2839 .word set_fd_dbl_f10 2840 .word set_fd_dbl_f12 2841 .word set_fd_dbl_f14 2842 .word set_fd_dbl_f16 2843 .word set_fd_dbl_f18 2844 .word set_fd_dbl_f20 2845 .word set_fd_dbl_f22 2846 .word set_fd_dbl_f24 2847 .word set_fd_dbl_f26 2848 .word set_fd_dbl_f28 2849 .word set_fd_dbl_f30 2850 .text 2851 2852set_fd_dbl_f0: 2853 mtc1 t3, $f0 2854 mfc1 t0, $f1 2855 j ra 2856set_fd_dbl_f2: 2857 mtc1 t3, $f2 2858 mfc1 t0, $f3 2859 j ra 2860set_fd_dbl_f4: 2861 mtc1 t3, $f4 2862 mfc1 t0, $f5 2863 j ra 2864set_fd_dbl_f6: 2865 mtc1 t3, $f6 2866 mfc1 t0, $f7 2867 j ra 2868set_fd_dbl_f8: 2869 mtc1 t3, $f8 2870 mfc1 t0, $f9 2871 j ra 2872set_fd_dbl_f10: 2873 mtc1 t3, $f10 2874 mfc1 t0, $f11 2875 j ra 2876set_fd_dbl_f12: 2877 mtc1 t3, $f12 2878 mfc1 t0, $f13 2879 j ra 2880set_fd_dbl_f14: 2881 mtc1 t3, $f14 2882 mfc1 t0, $f15 2883 j ra 2884set_fd_dbl_f16: 2885 mtc1 t3, $f16 2886 mfc1 t0, $f17 2887 j ra 2888set_fd_dbl_f18: 2889 mtc1 t3, $f18 2890 mfc1 t0, $f19 2891 j ra 2892set_fd_dbl_f20: 2893 mtc1 t3, $f20 2894 mfc1 t0, $f21 2895 j ra 2896set_fd_dbl_f22: 2897 mtc1 t3, $f22 2898 mfc1 t0, $f23 2899 j ra 2900set_fd_dbl_f24: 2901 mtc1 t3, $f24 2902 mfc1 t0, $f25 2903 j ra 2904set_fd_dbl_f26: 2905 mtc1 t3, $f26 2906 mfc1 t0, $f27 2907 j ra 2908set_fd_dbl_f28: 2909 mtc1 t3, $f28 2910 mfc1 t0, $f29 2911 j ra 2912set_fd_dbl_f30: 2913 mtc1 t3, $f30 2914 mfc1 t0, $f31 2915 j ra 2916END(set_fd_dbl) 2917 2918/*---------------------------------------------------------------------------- 2919 * renorm_fs_s -- 2920 * 2921 * Results: 2922 * t1 unbiased exponent 2923 * t2 normalized fraction 2924 * 2925 *---------------------------------------------------------------------------- 2926 */ 2927LEAF(renorm_fs_s) 2928/* 2929 * Find out how many leading zero bits are in t2 and put in t9. 2930 */ 2931 move v0, t2 2932 move t9, zero 2933 srl v1, v0, 16 2934 bne v1, zero, 1f 2935 addu t9, 16 2936 sll v0, 16 29371: 2938 srl v1, v0, 24 2939 bne v1, zero, 1f 2940 addu t9, 8 2941 sll v0, 8 29421: 2943 srl v1, v0, 28 2944 bne v1, zero, 1f 2945 addu t9, 4 2946 sll v0, 4 29471: 2948 srl v1, v0, 30 2949 bne v1, zero, 1f 2950 addu t9, 2 2951 sll v0, 2 29521: 2953 srl v1, v0, 31 2954 bne v1, zero, 1f 2955 addu t9, 1 2956/* 2957 * Now shift t2 the correct number of bits. 2958 */ 29591: 2960 subu t9, t9, SLEAD_ZEROS # don't count normal leading zeros 2961 li t1, SEXP_MIN 2962 subu t1, t1, t9 # adjust exponent 2963 sll t2, t2, t9 2964 j ra 2965END(renorm_fs_s) 2966 2967/*---------------------------------------------------------------------------- 2968 * renorm_fs_d -- 2969 * 2970 * Results: 2971 * t1 unbiased exponent 2972 * t2,t3 normalized fraction 2973 * 2974 *---------------------------------------------------------------------------- 2975 */ 2976LEAF(renorm_fs_d) 2977/* 2978 * Find out how many leading zero bits are in t2,t3 and put in t9. 2979 */ 2980 move v0, t2 2981 move t9, zero 2982 bne t2, zero, 1f 2983 move v0, t3 2984 addu t9, 32 29851: 2986 srl v1, v0, 16 2987 bne v1, zero, 1f 2988 addu t9, 16 2989 sll v0, 16 29901: 2991 srl v1, v0, 24 2992 bne v1, zero, 1f 2993 addu t9, 8 2994 sll v0, 8 29951: 2996 srl v1, v0, 28 2997 bne v1, zero, 1f 2998 addu t9, 4 2999 sll v0, 4 30001: 3001 srl v1, v0, 30 3002 bne v1, zero, 1f 3003 addu t9, 2 3004 sll v0, 2 30051: 3006 srl v1, v0, 31 3007 bne v1, zero, 1f 3008 addu t9, 1 3009/* 3010 * Now shift t2,t3 the correct number of bits. 3011 */ 30121: 3013 subu t9, t9, DLEAD_ZEROS # don't count normal leading zeros 3014 li t1, DEXP_MIN 3015 subu t1, t1, t9 # adjust exponent 3016 li v0, 32 3017 blt t9, v0, 1f 3018 subu t9, t9, v0 # shift fraction left >= 32 bits 3019 sll t2, t3, t9 3020 move t3, zero 3021 j ra 30221: 3023 subu v0, v0, t9 # shift fraction left < 32 bits 3024 sll t2, t2, t9 3025 srl v1, t3, v0 3026 or t2, t2, v1 3027 sll t3, t3, t9 3028 j ra 3029END(renorm_fs_d) 3030 3031/*---------------------------------------------------------------------------- 3032 * renorm_ft_s -- 3033 * 3034 * Results: 3035 * t5 unbiased exponent 3036 * t6 normalized fraction 3037 * 3038 *---------------------------------------------------------------------------- 3039 */ 3040LEAF(renorm_ft_s) 3041/* 3042 * Find out how many leading zero bits are in t6 and put in t9. 3043 */ 3044 move v0, t6 3045 move t9, zero 3046 srl v1, v0, 16 3047 bne v1, zero, 1f 3048 addu t9, 16 3049 sll v0, 16 30501: 3051 srl v1, v0, 24 3052 bne v1, zero, 1f 3053 addu t9, 8 3054 sll v0, 8 30551: 3056 srl v1, v0, 28 3057 bne v1, zero, 1f 3058 addu t9, 4 3059 sll v0, 4 30601: 3061 srl v1, v0, 30 3062 bne v1, zero, 1f 3063 addu t9, 2 3064 sll v0, 2 30651: 3066 srl v1, v0, 31 3067 bne v1, zero, 1f 3068 addu t9, 1 3069/* 3070 * Now shift t6 the correct number of bits. 3071 */ 30721: 3073 subu t9, t9, SLEAD_ZEROS # don't count normal leading zeros 3074 li t5, SEXP_MIN 3075 subu t5, t5, t9 # adjust exponent 3076 sll t6, t6, t9 3077 j ra 3078END(renorm_ft_s) 3079 3080/*---------------------------------------------------------------------------- 3081 * renorm_ft_d -- 3082 * 3083 * Results: 3084 * t5 unbiased exponent 3085 * t6,t7 normalized fraction 3086 * 3087 *---------------------------------------------------------------------------- 3088 */ 3089LEAF(renorm_ft_d) 3090/* 3091 * Find out how many leading zero bits are in t6,t7 and put in t9. 3092 */ 3093 move v0, t6 3094 move t9, zero 3095 bne t6, zero, 1f 3096 move v0, t7 3097 addu t9, 32 30981: 3099 srl v1, v0, 16 3100 bne v1, zero, 1f 3101 addu t9, 16 3102 sll v0, 16 31031: 3104 srl v1, v0, 24 3105 bne v1, zero, 1f 3106 addu t9, 8 3107 sll v0, 8 31081: 3109 srl v1, v0, 28 3110 bne v1, zero, 1f 3111 addu t9, 4 3112 sll v0, 4 31131: 3114 srl v1, v0, 30 3115 bne v1, zero, 1f 3116 addu t9, 2 3117 sll v0, 2 31181: 3119 srl v1, v0, 31 3120 bne v1, zero, 1f 3121 addu t9, 1 3122/* 3123 * Now shift t6,t7 the correct number of bits. 3124 */ 31251: 3126 subu t9, t9, DLEAD_ZEROS # don't count normal leading zeros 3127 li t5, DEXP_MIN 3128 subu t5, t5, t9 # adjust exponent 3129 li v0, 32 3130 blt t9, v0, 1f 3131 subu t9, t9, v0 # shift fraction left >= 32 bits 3132 sll t6, t7, t9 3133 move t7, zero 3134 j ra 31351: 3136 subu v0, v0, t9 # shift fraction left < 32 bits 3137 sll t6, t6, t9 3138 srl v1, t7, v0 3139 or t6, t6, v1 3140 sll t7, t7, t9 3141 j ra 3142END(renorm_ft_d) 3143