1/* $OpenBSD: fp.S,v 1.2 1998/03/16 09:03:31 pefo Exp $ */ 2/*- 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * Ralph Campbell. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * from: @(#)fp.s 8.1 (Berkeley) 6/10/93 34 * JNPR: fp.S,v 1.1 2006/08/07 05:38:57 katta 35 * $FreeBSD$ 36 */ 37 38/* 39 * Standard header stuff. 40 */ 41 42#include <machine/asm.h> 43#include <machine/regnum.h> 44#include <machine/cpuregs.h> 45 46#include "assym.s" 47 48#define SEXP_INF 0xff 49#define DEXP_INF 0x7ff 50#define SEXP_BIAS 127 51#define DEXP_BIAS 1023 52#define SEXP_MIN -126 53#define DEXP_MIN -1022 54#define SEXP_MAX 127 55#define DEXP_MAX 1023 56#define WEXP_MAX 30 /* maximum unbiased exponent for int */ 57#define WEXP_MIN -1 /* minimum unbiased exponent for int */ 58#define SFRAC_BITS 23 59#define DFRAC_BITS 52 60#define SIMPL_ONE 0x00800000 61#define DIMPL_ONE 0x00100000 62#define SLEAD_ZEROS 31 - 23 63#define DLEAD_ZEROS 31 - 20 64#define STICKYBIT 1 65#define GUARDBIT 0x80000000 66#define SSIGNAL_NAN 0x00400000 67#define DSIGNAL_NAN 0x00080000 68#define SQUIET_NAN 0x003fffff 69#define DQUIET_NAN0 0x0007ffff 70#define DQUIET_NAN1 0xffffffff 71#define INT_MIN 0x80000000 72#define INT_MAX 0x7fffffff 73 74#define COND_UNORDERED 0x1 75#define COND_EQUAL 0x2 76#define COND_LESS 0x4 77#define COND_SIGNAL 0x8 78 79/*---------------------------------------------------------------------------- 80 * 81 * MipsEmulateFP -- 82 * 83 * Emulate unimplemented floating point operations. 84 * This routine should only be called by MipsFPInterrupt(). 85 * 86 * MipsEmulateFP(instr) 87 * unsigned instr; 88 * 89 * Results: 90 * None. 91 * 92 * Side effects: 93 * Floating point registers are modified according to instruction. 94 * 95 *---------------------------------------------------------------------------- 96 */ 97NON_LEAF(MipsEmulateFP, CALLFRAME_SIZ, ra) 98 subu sp, sp, CALLFRAME_SIZ 99 sw ra, CALLFRAME_RA(sp) 100/* 101 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0). 102 */ 103 srl v0, a0, 21 - 2 # get FMT field 104 and v0, v0, 0xF << 2 # mask FMT field 105 and v1, a0, 0x3F # mask FUNC field 106 sll v1, v1, 5 # align for table lookup 107 bgt v0, 4 << 2, ill # illegal format 108 109 or v1, v1, v0 110 cfc1 a1, MIPS_FPU_CSR # get exception register 111 lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT 112 and a1, a1, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception 113 ctc1 a1, MIPS_FPU_CSR 114 j a3 115 116 .rdata 117func_fmt_tbl: 118 .word add_s # 0 119 .word add_d # 0 120 .word ill # 0 121 .word ill # 0 122 .word ill # 0 123 .word ill # 0 124 .word ill # 0 125 .word ill # 0 126 .word sub_s # 1 127 .word sub_d # 1 128 .word ill # 1 129 .word ill # 1 130 .word ill # 1 131 .word ill # 1 132 .word ill # 1 133 .word ill # 1 134 .word mul_s # 2 135 .word mul_d # 2 136 .word ill # 2 137 .word ill # 2 138 .word ill # 2 139 .word ill # 2 140 .word ill # 2 141 .word ill # 2 142 .word div_s # 3 143 .word div_d # 3 144 .word ill # 3 145 .word ill # 3 146 .word ill # 3 147 .word ill # 3 148 .word ill # 3 149 .word ill # 3 150 .word ill # 4 151 .word ill # 4 152 .word ill # 4 153 .word ill # 4 154 .word ill # 4 155 .word ill # 4 156 .word ill # 4 157 .word ill # 4 158 .word abs_s # 5 159 .word abs_d # 5 160 .word ill # 5 161 .word ill # 5 162 .word ill # 5 163 .word ill # 5 164 .word ill # 5 165 .word ill # 5 166 .word mov_s # 6 167 .word mov_d # 6 168 .word ill # 6 169 .word ill # 6 170 .word ill # 6 171 .word ill # 6 172 .word ill # 6 173 .word ill # 6 174 .word neg_s # 7 175 .word neg_d # 7 176 .word ill # 7 177 .word ill # 7 178 .word ill # 7 179 .word ill # 7 180 .word ill # 7 181 .word ill # 7 182 .word ill # 8 183 .word ill # 8 184 .word ill # 8 185 .word ill # 8 186 .word ill # 8 187 .word ill # 8 188 .word ill # 8 189 .word ill # 8 190 .word ill # 9 191 .word ill # 9 192 .word ill # 9 193 .word ill # 9 194 .word ill # 9 195 .word ill # 9 196 .word ill # 9 197 .word ill # 9 198 .word ill # 10 199 .word ill # 10 200 .word ill # 10 201 .word ill # 10 202 .word ill # 10 203 .word ill # 10 204 .word ill # 10 205 .word ill # 10 206 .word ill # 11 207 .word ill # 11 208 .word ill # 11 209 .word ill # 11 210 .word ill # 11 211 .word ill # 11 212 .word ill # 11 213 .word ill # 11 214 .word ill # 12 215 .word ill # 12 216 .word ill # 12 217 .word ill # 12 218 .word ill # 12 219 .word ill # 12 220 .word ill # 12 221 .word ill # 12 222 .word ill # 13 223 .word ill # 13 224 .word ill # 13 225 .word ill # 13 226 .word ill # 13 227 .word ill # 13 228 .word ill # 13 229 .word ill # 13 230 .word ill # 14 231 .word ill # 14 232 .word ill # 14 233 .word ill # 14 234 .word ill # 14 235 .word ill # 14 236 .word ill # 14 237 .word ill # 14 238 .word ill # 15 239 .word ill # 15 240 .word ill # 15 241 .word ill # 15 242 .word ill # 15 243 .word ill # 15 244 .word ill # 15 245 .word ill # 15 246 .word ill # 16 247 .word ill # 16 248 .word ill # 16 249 .word ill # 16 250 .word ill # 16 251 .word ill # 16 252 .word ill # 16 253 .word ill # 16 254 .word ill # 17 255 .word ill # 17 256 .word ill # 17 257 .word ill # 17 258 .word ill # 17 259 .word ill # 17 260 .word ill # 17 261 .word ill # 17 262 .word ill # 18 263 .word ill # 18 264 .word ill # 18 265 .word ill # 18 266 .word ill # 18 267 .word ill # 18 268 .word ill # 18 269 .word ill # 18 270 .word ill # 19 271 .word ill # 19 272 .word ill # 19 273 .word ill # 19 274 .word ill # 19 275 .word ill # 19 276 .word ill # 19 277 .word ill # 19 278 .word ill # 20 279 .word ill # 20 280 .word ill # 20 281 .word ill # 20 282 .word ill # 20 283 .word ill # 20 284 .word ill # 20 285 .word ill # 20 286 .word ill # 21 287 .word ill # 21 288 .word ill # 21 289 .word ill # 21 290 .word ill # 21 291 .word ill # 21 292 .word ill # 21 293 .word ill # 21 294 .word ill # 22 295 .word ill # 22 296 .word ill # 22 297 .word ill # 22 298 .word ill # 22 299 .word ill # 22 300 .word ill # 22 301 .word ill # 22 302 .word ill # 23 303 .word ill # 23 304 .word ill # 23 305 .word ill # 23 306 .word ill # 23 307 .word ill # 23 308 .word ill # 23 309 .word ill # 23 310 .word ill # 24 311 .word ill # 24 312 .word ill # 24 313 .word ill # 24 314 .word ill # 24 315 .word ill # 24 316 .word ill # 24 317 .word ill # 24 318 .word ill # 25 319 .word ill # 25 320 .word ill # 25 321 .word ill # 25 322 .word ill # 25 323 .word ill # 25 324 .word ill # 25 325 .word ill # 25 326 .word ill # 26 327 .word ill # 26 328 .word ill # 26 329 .word ill # 26 330 .word ill # 26 331 .word ill # 26 332 .word ill # 26 333 .word ill # 26 334 .word ill # 27 335 .word ill # 27 336 .word ill # 27 337 .word ill # 27 338 .word ill # 27 339 .word ill # 27 340 .word ill # 27 341 .word ill # 27 342 .word ill # 28 343 .word ill # 28 344 .word ill # 28 345 .word ill # 28 346 .word ill # 28 347 .word ill # 28 348 .word ill # 28 349 .word ill # 28 350 .word ill # 29 351 .word ill # 29 352 .word ill # 29 353 .word ill # 29 354 .word ill # 29 355 .word ill # 29 356 .word ill # 29 357 .word ill # 29 358 .word ill # 30 359 .word ill # 30 360 .word ill # 30 361 .word ill # 30 362 .word ill # 30 363 .word ill # 30 364 .word ill # 30 365 .word ill # 30 366 .word ill # 31 367 .word ill # 31 368 .word ill # 31 369 .word ill # 31 370 .word ill # 31 371 .word ill # 31 372 .word ill # 31 373 .word ill # 31 374 .word ill # 32 375 .word cvt_s_d # 32 376 .word ill # 32 377 .word ill # 32 378 .word cvt_s_w # 32 379 .word ill # 32 380 .word ill # 32 381 .word ill # 32 382 .word cvt_d_s # 33 383 .word ill # 33 384 .word ill # 33 385 .word ill # 33 386 .word cvt_d_w # 33 387 .word ill # 33 388 .word ill # 33 389 .word ill # 33 390 .word ill # 34 391 .word ill # 34 392 .word ill # 34 393 .word ill # 34 394 .word ill # 34 395 .word ill # 34 396 .word ill # 34 397 .word ill # 34 398 .word ill # 35 399 .word ill # 35 400 .word ill # 35 401 .word ill # 35 402 .word ill # 35 403 .word ill # 35 404 .word ill # 35 405 .word ill # 35 406 .word cvt_w_s # 36 407 .word cvt_w_d # 36 408 .word ill # 36 409 .word ill # 36 410 .word ill # 36 411 .word ill # 36 412 .word ill # 36 413 .word ill # 36 414 .word ill # 37 415 .word ill # 37 416 .word ill # 37 417 .word ill # 37 418 .word ill # 37 419 .word ill # 37 420 .word ill # 37 421 .word ill # 37 422 .word ill # 38 423 .word ill # 38 424 .word ill # 38 425 .word ill # 38 426 .word ill # 38 427 .word ill # 38 428 .word ill # 38 429 .word ill # 38 430 .word ill # 39 431 .word ill # 39 432 .word ill # 39 433 .word ill # 39 434 .word ill # 39 435 .word ill # 39 436 .word ill # 39 437 .word ill # 39 438 .word ill # 40 439 .word ill # 40 440 .word ill # 40 441 .word ill # 40 442 .word ill # 40 443 .word ill # 40 444 .word ill # 40 445 .word ill # 40 446 .word ill # 41 447 .word ill # 41 448 .word ill # 41 449 .word ill # 41 450 .word ill # 41 451 .word ill # 41 452 .word ill # 41 453 .word ill # 41 454 .word ill # 42 455 .word ill # 42 456 .word ill # 42 457 .word ill # 42 458 .word ill # 42 459 .word ill # 42 460 .word ill # 42 461 .word ill # 42 462 .word ill # 43 463 .word ill # 43 464 .word ill # 43 465 .word ill # 43 466 .word ill # 43 467 .word ill # 43 468 .word ill # 43 469 .word ill # 43 470 .word ill # 44 471 .word ill # 44 472 .word ill # 44 473 .word ill # 44 474 .word ill # 44 475 .word ill # 44 476 .word ill # 44 477 .word ill # 44 478 .word ill # 45 479 .word ill # 45 480 .word ill # 45 481 .word ill # 45 482 .word ill # 45 483 .word ill # 45 484 .word ill # 45 485 .word ill # 45 486 .word ill # 46 487 .word ill # 46 488 .word ill # 46 489 .word ill # 46 490 .word ill # 46 491 .word ill # 46 492 .word ill # 46 493 .word ill # 46 494 .word ill # 47 495 .word ill # 47 496 .word ill # 47 497 .word ill # 47 498 .word ill # 47 499 .word ill # 47 500 .word ill # 47 501 .word ill # 47 502 .word cmp_s # 48 503 .word cmp_d # 48 504 .word ill # 48 505 .word ill # 48 506 .word ill # 48 507 .word ill # 48 508 .word ill # 48 509 .word ill # 48 510 .word cmp_s # 49 511 .word cmp_d # 49 512 .word ill # 49 513 .word ill # 49 514 .word ill # 49 515 .word ill # 49 516 .word ill # 49 517 .word ill # 49 518 .word cmp_s # 50 519 .word cmp_d # 50 520 .word ill # 50 521 .word ill # 50 522 .word ill # 50 523 .word ill # 50 524 .word ill # 50 525 .word ill # 50 526 .word cmp_s # 51 527 .word cmp_d # 51 528 .word ill # 51 529 .word ill # 51 530 .word ill # 51 531 .word ill # 51 532 .word ill # 51 533 .word ill # 51 534 .word cmp_s # 52 535 .word cmp_d # 52 536 .word ill # 52 537 .word ill # 52 538 .word ill # 52 539 .word ill # 52 540 .word ill # 52 541 .word ill # 52 542 .word cmp_s # 53 543 .word cmp_d # 53 544 .word ill # 53 545 .word ill # 53 546 .word ill # 53 547 .word ill # 53 548 .word ill # 53 549 .word ill # 53 550 .word cmp_s # 54 551 .word cmp_d # 54 552 .word ill # 54 553 .word ill # 54 554 .word ill # 54 555 .word ill # 54 556 .word ill # 54 557 .word ill # 54 558 .word cmp_s # 55 559 .word cmp_d # 55 560 .word ill # 55 561 .word ill # 55 562 .word ill # 55 563 .word ill # 55 564 .word ill # 55 565 .word ill # 55 566 .word cmp_s # 56 567 .word cmp_d # 56 568 .word ill # 56 569 .word ill # 56 570 .word ill # 56 571 .word ill # 56 572 .word ill # 56 573 .word ill # 56 574 .word cmp_s # 57 575 .word cmp_d # 57 576 .word ill # 57 577 .word ill # 57 578 .word ill # 57 579 .word ill # 57 580 .word ill # 57 581 .word ill # 57 582 .word cmp_s # 58 583 .word cmp_d # 58 584 .word ill # 58 585 .word ill # 58 586 .word ill # 58 587 .word ill # 58 588 .word ill # 58 589 .word ill # 58 590 .word cmp_s # 59 591 .word cmp_d # 59 592 .word ill # 59 593 .word ill # 59 594 .word ill # 59 595 .word ill # 59 596 .word ill # 59 597 .word ill # 59 598 .word cmp_s # 60 599 .word cmp_d # 60 600 .word ill # 60 601 .word ill # 60 602 .word ill # 60 603 .word ill # 60 604 .word ill # 60 605 .word ill # 60 606 .word cmp_s # 61 607 .word cmp_d # 61 608 .word ill # 61 609 .word ill # 61 610 .word ill # 61 611 .word ill # 61 612 .word ill # 61 613 .word ill # 61 614 .word cmp_s # 62 615 .word cmp_d # 62 616 .word ill # 62 617 .word ill # 62 618 .word ill # 62 619 .word ill # 62 620 .word ill # 62 621 .word ill # 62 622 .word cmp_s # 63 623 .word cmp_d # 63 624 .word ill # 63 625 .word ill # 63 626 .word ill # 63 627 .word ill # 63 628 .word ill # 63 629 .word ill # 63 630 .text 631 632/* 633 * Single precision subtract. 634 */ 635sub_s: 636 jal get_ft_fs_s 637 xor ta0, ta0, 1 # negate FT sign bit 638 b add_sub_s 639/* 640 * Single precision add. 641 */ 642add_s: 643 jal get_ft_fs_s 644add_sub_s: 645 bne t1, SEXP_INF, 1f # is FS an infinity? 646 bne ta1, SEXP_INF, result_fs_s # if FT is not inf, result=FS 647 bne t2, zero, result_fs_s # if FS is NAN, result is FS 648 bne ta2, zero, result_ft_s # if FT is NAN, result is FT 649 bne t0, ta0, invalid_s # both infinities same sign? 650 b result_fs_s # result is in FS 6511: 652 beq ta1, SEXP_INF, result_ft_s # if FT is inf, result=FT 653 bne t1, zero, 4f # is FS a denormalized num? 654 beq t2, zero, 3f # is FS zero? 655 bne ta1, zero, 2f # is FT a denormalized num? 656 beq ta2, zero, result_fs_s # FT is zero, result=FS 657 jal renorm_fs_s 658 jal renorm_ft_s 659 b 5f 6602: 661 jal renorm_fs_s 662 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 663 or ta2, ta2, SIMPL_ONE # set implied one bit 664 b 5f 6653: 666 bne ta1, zero, result_ft_s # if FT != 0, result=FT 667 bne ta2, zero, result_ft_s 668 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 669 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 670 or t0, t0, ta0 # compute result sign 671 b result_fs_s 6721: 673 and t0, t0, ta0 # compute result sign 674 b result_fs_s 6754: 676 bne ta1, zero, 2f # is FT a denormalized num? 677 beq ta2, zero, result_fs_s # FT is zero, result=FS 678 subu t1, t1, SEXP_BIAS # unbias FS exponent 679 or t2, t2, SIMPL_ONE # set implied one bit 680 jal renorm_ft_s 681 b 5f 6822: 683 subu t1, t1, SEXP_BIAS # unbias FS exponent 684 or t2, t2, SIMPL_ONE # set implied one bit 685 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 686 or ta2, ta2, SIMPL_ONE # set implied one bit 687/* 688 * Perform the addition. 689 */ 6905: 691 move t8, zero # no shifted bits (sticky reg) 692 beq t1, ta1, 4f # no shift needed 693 subu v0, t1, ta1 # v0 = difference of exponents 694 move v1, v0 # v1 = abs(difference) 695 bge v0, zero, 1f 696 negu v1 6971: 698 ble v1, SFRAC_BITS+2, 2f # is difference too great? 699 li t8, STICKYBIT # set the sticky bit 700 bge v0, zero, 1f # check which exp is larger 701 move t1, ta1 # result exp is FTs 702 move t2, zero # FSs fraction shifted is zero 703 b 4f 7041: 705 move ta2, zero # FTs fraction shifted is zero 706 b 4f 7072: 708 li t9, 32 # compute 32 - abs(exp diff) 709 subu t9, t9, v1 710 bgt v0, zero, 3f # if FS > FT, shift FTs frac 711 move t1, ta1 # FT > FS, result exp is FTs 712 sll t8, t2, t9 # save bits shifted out 713 srl t2, t2, v1 # shift FSs fraction 714 b 4f 7153: 716 sll t8, ta2, t9 # save bits shifted out 717 srl ta2, ta2, v1 # shift FTs fraction 7184: 719 bne t0, ta0, 1f # if signs differ, subtract 720 addu t2, t2, ta2 # add fractions 721 b norm_s 7221: 723 blt t2, ta2, 3f # subtract larger from smaller 724 bne t2, ta2, 2f # if same, result=0 725 move t1, zero # result=0 726 move t2, zero 727 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 728 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 729 or t0, t0, ta0 # compute result sign 730 b result_fs_s 7311: 732 and t0, t0, ta0 # compute result sign 733 b result_fs_s 7342: 735 sltu t9, zero, t8 # compute t2:zero - ta2:t8 736 subu t8, zero, t8 737 subu t2, t2, ta2 # subtract fractions 738 subu t2, t2, t9 # subtract barrow 739 b norm_s 7403: 741 move t0, ta0 # sign of result = FTs 742 sltu t9, zero, t8 # compute ta2:zero - t2:t8 743 subu t8, zero, t8 744 subu t2, ta2, t2 # subtract fractions 745 subu t2, t2, t9 # subtract barrow 746 b norm_s 747 748/* 749 * Double precision subtract. 750 */ 751sub_d: 752 jal get_ft_fs_d 753 xor ta0, ta0, 1 # negate sign bit 754 b add_sub_d 755/* 756 * Double precision add. 757 */ 758add_d: 759 jal get_ft_fs_d 760add_sub_d: 761 bne t1, DEXP_INF, 1f # is FS an infinity? 762 bne ta1, DEXP_INF, result_fs_d # if FT is not inf, result=FS 763 bne t2, zero, result_fs_d # if FS is NAN, result is FS 764 bne t3, zero, result_fs_d 765 bne ta2, zero, result_ft_d # if FT is NAN, result is FT 766 bne ta3, zero, result_ft_d 767 bne t0, ta0, invalid_d # both infinities same sign? 768 b result_fs_d # result is in FS 7691: 770 beq ta1, DEXP_INF, result_ft_d # if FT is inf, result=FT 771 bne t1, zero, 4f # is FS a denormalized num? 772 bne t2, zero, 1f # is FS zero? 773 beq t3, zero, 3f 7741: 775 bne ta1, zero, 2f # is FT a denormalized num? 776 bne ta2, zero, 1f 777 beq ta3, zero, result_fs_d # FT is zero, result=FS 7781: 779 jal renorm_fs_d 780 jal renorm_ft_d 781 b 5f 7822: 783 jal renorm_fs_d 784 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 785 or ta2, ta2, DIMPL_ONE # set implied one bit 786 b 5f 7873: 788 bne ta1, zero, result_ft_d # if FT != 0, result=FT 789 bne ta2, zero, result_ft_d 790 bne ta3, zero, result_ft_d 791 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 792 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 793 or t0, t0, ta0 # compute result sign 794 b result_fs_d 7951: 796 and t0, t0, ta0 # compute result sign 797 b result_fs_d 7984: 799 bne ta1, zero, 2f # is FT a denormalized num? 800 bne ta2, zero, 1f 801 beq ta3, zero, result_fs_d # FT is zero, result=FS 8021: 803 subu t1, t1, DEXP_BIAS # unbias FS exponent 804 or t2, t2, DIMPL_ONE # set implied one bit 805 jal renorm_ft_d 806 b 5f 8072: 808 subu t1, t1, DEXP_BIAS # unbias FS exponent 809 or t2, t2, DIMPL_ONE # set implied one bit 810 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 811 or ta2, ta2, DIMPL_ONE # set implied one bit 812/* 813 * Perform the addition. 814 */ 8155: 816 move t8, zero # no shifted bits (sticky reg) 817 beq t1, ta1, 4f # no shift needed 818 subu v0, t1, ta1 # v0 = difference of exponents 819 move v1, v0 # v1 = abs(difference) 820 bge v0, zero, 1f 821 negu v1 8221: 823 ble v1, DFRAC_BITS+2, 2f # is difference too great? 824 li t8, STICKYBIT # set the sticky bit 825 bge v0, zero, 1f # check which exp is larger 826 move t1, ta1 # result exp is FTs 827 move t2, zero # FSs fraction shifted is zero 828 move t3, zero 829 b 4f 8301: 831 move ta2, zero # FTs fraction shifted is zero 832 move ta3, zero 833 b 4f 8342: 835 li t9, 32 836 bge v0, zero, 3f # if FS > FT, shift FTs frac 837 move t1, ta1 # FT > FS, result exp is FTs 838 blt v1, t9, 1f # shift right by < 32? 839 subu v1, v1, t9 840 subu t9, t9, v1 841 sll t8, t2, t9 # save bits shifted out 842 sltu t9, zero, t3 # dont lose any one bits 843 or t8, t8, t9 # save sticky bit 844 srl t3, t2, v1 # shift FSs fraction 845 move t2, zero 846 b 4f 8471: 848 subu t9, t9, v1 849 sll t8, t3, t9 # save bits shifted out 850 srl t3, t3, v1 # shift FSs fraction 851 sll t9, t2, t9 # save bits shifted out of t2 852 or t3, t3, t9 # and put into t3 853 srl t2, t2, v1 854 b 4f 8553: 856 blt v1, t9, 1f # shift right by < 32? 857 subu v1, v1, t9 858 subu t9, t9, v1 859 sll t8, ta2, t9 # save bits shifted out 860 srl ta3, ta2, v1 # shift FTs fraction 861 move ta2, zero 862 b 4f 8631: 864 subu t9, t9, v1 865 sll t8, ta3, t9 # save bits shifted out 866 srl ta3, ta3, v1 # shift FTs fraction 867 sll t9, ta2, t9 # save bits shifted out of t2 868 or ta3, ta3, t9 # and put into t3 869 srl ta2, ta2, v1 8704: 871 bne t0, ta0, 1f # if signs differ, subtract 872 addu t3, t3, ta3 # add fractions 873 sltu t9, t3, ta3 # compute carry 874 addu t2, t2, ta2 # add fractions 875 addu t2, t2, t9 # add carry 876 b norm_d 8771: 878 blt t2, ta2, 3f # subtract larger from smaller 879 bne t2, ta2, 2f 880 bltu t3, ta3, 3f 881 bne t3, ta3, 2f # if same, result=0 882 move t1, zero # result=0 883 move t2, zero 884 move t3, zero 885 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 886 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 887 or t0, t0, ta0 # compute result sign 888 b result_fs_d 8891: 890 and t0, t0, ta0 # compute result sign 891 b result_fs_d 8922: 893 beq t8, zero, 1f # compute t2:t3:zero - ta2:ta3:t8 894 subu t8, zero, t8 895 sltu v0, t3, 1 # compute barrow out 896 subu t3, t3, 1 # subtract barrow 897 subu t2, t2, v0 8981: 899 sltu v0, t3, ta3 900 subu t3, t3, ta3 # subtract fractions 901 subu t2, t2, ta2 # subtract fractions 902 subu t2, t2, v0 # subtract barrow 903 b norm_d 9043: 905 move t0, ta0 # sign of result = FTs 906 beq t8, zero, 1f # compute ta2:ta3:zero - t2:t3:t8 907 subu t8, zero, t8 908 sltu v0, ta3, 1 # compute barrow out 909 subu ta3, ta3, 1 # subtract barrow 910 subu ta2, ta2, v0 9111: 912 sltu v0, ta3, t3 913 subu t3, ta3, t3 # subtract fractions 914 subu t2, ta2, t2 # subtract fractions 915 subu t2, t2, v0 # subtract barrow 916 b norm_d 917 918/* 919 * Single precision multiply. 920 */ 921mul_s: 922 jal get_ft_fs_s 923 xor t0, t0, ta0 # compute sign of result 924 move ta0, t0 925 bne t1, SEXP_INF, 2f # is FS an infinity? 926 bne t2, zero, result_fs_s # if FS is a NAN, result=FS 927 bne ta1, SEXP_INF, 1f # FS is inf, is FT an infinity? 928 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT 929 b result_fs_s # result is infinity 9301: 931 bne ta1, zero, result_fs_s # inf * zero? if no, result=FS 932 bne ta2, zero, result_fs_s 933 b invalid_s # infinity * zero is invalid 9342: 935 bne ta1, SEXP_INF, 1f # FS != inf, is FT an infinity? 936 bne t1, zero, result_ft_s # zero * inf? if no, result=FT 937 bne t2, zero, result_ft_s 938 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT 939 b invalid_s # zero * infinity is invalid 9401: 941 bne t1, zero, 1f # is FS zero? 942 beq t2, zero, result_fs_s # result is zero 943 jal renorm_fs_s 944 b 2f 9451: 946 subu t1, t1, SEXP_BIAS # unbias FS exponent 947 or t2, t2, SIMPL_ONE # set implied one bit 9482: 949 bne ta1, zero, 1f # is FT zero? 950 beq ta2, zero, result_ft_s # result is zero 951 jal renorm_ft_s 952 b 2f 9531: 954 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 955 or ta2, ta2, SIMPL_ONE # set implied one bit 9562: 957 addu t1, t1, ta1 # compute result exponent 958 addu t1, t1, 9 # account for binary point 959 multu t2, ta2 # multiply fractions 960 mflo t8 961 mfhi t2 962 b norm_s 963 964/* 965 * Double precision multiply. 966 */ 967mul_d: 968 jal get_ft_fs_d 969 xor t0, t0, ta0 # compute sign of result 970 move ta0, t0 971 bne t1, DEXP_INF, 2f # is FS an infinity? 972 bne t2, zero, result_fs_d # if FS is a NAN, result=FS 973 bne t3, zero, result_fs_d 974 bne ta1, DEXP_INF, 1f # FS is inf, is FT an infinity? 975 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT 976 bne ta3, zero, result_ft_d 977 b result_fs_d # result is infinity 9781: 979 bne ta1, zero, result_fs_d # inf * zero? if no, result=FS 980 bne ta2, zero, result_fs_d 981 bne ta3, zero, result_fs_d 982 b invalid_d # infinity * zero is invalid 9832: 984 bne ta1, DEXP_INF, 1f # FS != inf, is FT an infinity? 985 bne t1, zero, result_ft_d # zero * inf? if no, result=FT 986 bne t2, zero, result_ft_d # if FS is a NAN, result=FS 987 bne t3, zero, result_ft_d 988 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT 989 bne ta3, zero, result_ft_d 990 b invalid_d # zero * infinity is invalid 9911: 992 bne t1, zero, 2f # is FS zero? 993 bne t2, zero, 1f 994 beq t3, zero, result_fs_d # result is zero 9951: 996 jal renorm_fs_d 997 b 3f 9982: 999 subu t1, t1, DEXP_BIAS # unbias FS exponent 1000 or t2, t2, DIMPL_ONE # set implied one bit 10013: 1002 bne ta1, zero, 2f # is FT zero? 1003 bne ta2, zero, 1f 1004 beq ta3, zero, result_ft_d # result is zero 10051: 1006 jal renorm_ft_d 1007 b 3f 10082: 1009 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 1010 or ta2, ta2, DIMPL_ONE # set implied one bit 10113: 1012 addu t1, t1, ta1 # compute result exponent 1013 addu t1, t1, 12 # ??? 1014 multu t3, ta3 # multiply fractions (low * low) 1015 move ta0, t2 # free up t2,t3 for result 1016 move ta1, t3 1017 mflo a3 # save low order bits 1018 mfhi t8 1019 not v0, t8 1020 multu ta0, ta3 # multiply FS(high) * FT(low) 1021 mflo v1 1022 mfhi t3 # init low result 1023 sltu v0, v0, v1 # compute carry 1024 addu t8, v1 1025 multu ta1, ta2 # multiply FS(low) * FT(high) 1026 addu t3, t3, v0 # add carry 1027 not v0, t8 1028 mflo v1 1029 mfhi t2 1030 sltu v0, v0, v1 1031 addu t8, v1 1032 multu ta0, ta2 # multiply FS(high) * FT(high) 1033 addu t3, v0 1034 not v1, t3 1035 sltu v1, v1, t2 1036 addu t3, t2 1037 not v0, t3 1038 mfhi t2 1039 addu t2, v1 1040 mflo v1 1041 sltu v0, v0, v1 1042 addu t2, v0 1043 addu t3, v1 1044 sltu a3, zero, a3 # reduce t8,a3 to just t8 1045 or t8, a3 1046 b norm_d 1047 1048/* 1049 * Single precision divide. 1050 */ 1051div_s: 1052 jal get_ft_fs_s 1053 xor t0, t0, ta0 # compute sign of result 1054 move ta0, t0 1055 bne t1, SEXP_INF, 1f # is FS an infinity? 1056 bne t2, zero, result_fs_s # if FS is NAN, result is FS 1057 bne ta1, SEXP_INF, result_fs_s # is FT an infinity? 1058 bne ta2, zero, result_ft_s # if FT is NAN, result is FT 1059 b invalid_s # infinity/infinity is invalid 10601: 1061 bne ta1, SEXP_INF, 1f # is FT an infinity? 1062 bne ta2, zero, result_ft_s # if FT is NAN, result is FT 1063 move t1, zero # x / infinity is zero 1064 move t2, zero 1065 b result_fs_s 10661: 1067 bne t1, zero, 2f # is FS zero? 1068 bne t2, zero, 1f 1069 bne ta1, zero, result_fs_s # FS=zero, is FT zero? 1070 beq ta2, zero, invalid_s # 0 / 0 1071 b result_fs_s # result = zero 10721: 1073 jal renorm_fs_s 1074 b 3f 10752: 1076 subu t1, t1, SEXP_BIAS # unbias FS exponent 1077 or t2, t2, SIMPL_ONE # set implied one bit 10783: 1079 bne ta1, zero, 2f # is FT zero? 1080 bne ta2, zero, 1f 1081 or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0 1082 and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled? 1083 bne v0, zero, fpe_trap 1084 ctc1 a1, MIPS_FPU_CSR # save exceptions 1085 li t1, SEXP_INF # result is infinity 1086 move t2, zero 1087 b result_fs_s 10881: 1089 jal renorm_ft_s 1090 b 3f 10912: 1092 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 1093 or ta2, ta2, SIMPL_ONE # set implied one bit 10943: 1095 subu t1, t1, ta1 # compute exponent 1096 subu t1, t1, 3 # compensate for result position 1097 li v0, SFRAC_BITS+3 # number of bits to divide 1098 move t8, t2 # init dividend 1099 move t2, zero # init result 11001: 1101 bltu t8, ta2, 3f # is dividend >= divisor? 11022: 1103 subu t8, t8, ta2 # subtract divisor from dividend 1104 or t2, t2, 1 # remember that we did 1105 bne t8, zero, 3f # if not done, continue 1106 sll t2, t2, v0 # shift result to final position 1107 b norm_s 11083: 1109 sll t8, t8, 1 # shift dividend 1110 sll t2, t2, 1 # shift result 1111 subu v0, v0, 1 # are we done? 1112 bne v0, zero, 1b # no, continue 1113 b norm_s 1114 1115/* 1116 * Double precision divide. 1117 */ 1118div_d: 1119 jal get_ft_fs_d 1120 xor t0, t0, ta0 # compute sign of result 1121 move ta0, t0 1122 bne t1, DEXP_INF, 1f # is FS an infinity? 1123 bne t2, zero, result_fs_d # if FS is NAN, result is FS 1124 bne t3, zero, result_fs_d 1125 bne ta1, DEXP_INF, result_fs_d # is FT an infinity? 1126 bne ta2, zero, result_ft_d # if FT is NAN, result is FT 1127 bne ta3, zero, result_ft_d 1128 b invalid_d # infinity/infinity is invalid 11291: 1130 bne ta1, DEXP_INF, 1f # is FT an infinity? 1131 bne ta2, zero, result_ft_d # if FT is NAN, result is FT 1132 bne ta3, zero, result_ft_d 1133 move t1, zero # x / infinity is zero 1134 move t2, zero 1135 move t3, zero 1136 b result_fs_d 11371: 1138 bne t1, zero, 2f # is FS zero? 1139 bne t2, zero, 1f 1140 bne t3, zero, 1f 1141 bne ta1, zero, result_fs_d # FS=zero, is FT zero? 1142 bne ta2, zero, result_fs_d 1143 beq ta3, zero, invalid_d # 0 / 0 1144 b result_fs_d # result = zero 11451: 1146 jal renorm_fs_d 1147 b 3f 11482: 1149 subu t1, t1, DEXP_BIAS # unbias FS exponent 1150 or t2, t2, DIMPL_ONE # set implied one bit 11513: 1152 bne ta1, zero, 2f # is FT zero? 1153 bne ta2, zero, 1f 1154 bne ta3, zero, 1f 1155 or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0 1156 and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled? 1157 bne v0, zero, fpe_trap 1158 ctc1 a1, MIPS_FPU_CSR # Save exceptions 1159 li t1, DEXP_INF # result is infinity 1160 move t2, zero 1161 move t3, zero 1162 b result_fs_d 11631: 1164 jal renorm_ft_d 1165 b 3f 11662: 1167 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 1168 or ta2, ta2, DIMPL_ONE # set implied one bit 11693: 1170 subu t1, t1, ta1 # compute exponent 1171 subu t1, t1, 3 # compensate for result position 1172 li v0, DFRAC_BITS+3 # number of bits to divide 1173 move t8, t2 # init dividend 1174 move t9, t3 1175 move t2, zero # init result 1176 move t3, zero 11771: 1178 bltu t8, ta2, 3f # is dividend >= divisor? 1179 bne t8, ta2, 2f 1180 bltu t9, ta3, 3f 11812: 1182 sltu v1, t9, ta3 # subtract divisor from dividend 1183 subu t9, t9, ta3 1184 subu t8, t8, ta2 1185 subu t8, t8, v1 1186 or t3, t3, 1 # remember that we did 1187 bne t8, zero, 3f # if not done, continue 1188 bne t9, zero, 3f 1189 li v1, 32 # shift result to final position 1190 blt v0, v1, 2f # shift < 32 bits? 1191 subu v0, v0, v1 # shift by > 32 bits 1192 sll t2, t3, v0 # shift upper part 1193 move t3, zero 1194 b norm_d 11952: 1196 subu v1, v1, v0 # shift by < 32 bits 1197 sll t2, t2, v0 # shift upper part 1198 srl t9, t3, v1 # save bits shifted out 1199 or t2, t2, t9 # and put into upper part 1200 sll t3, t3, v0 1201 b norm_d 12023: 1203 sll t8, t8, 1 # shift dividend 1204 srl v1, t9, 31 # save bit shifted out 1205 or t8, t8, v1 # and put into upper part 1206 sll t9, t9, 1 1207 sll t2, t2, 1 # shift result 1208 srl v1, t3, 31 # save bit shifted out 1209 or t2, t2, v1 # and put into upper part 1210 sll t3, t3, 1 1211 subu v0, v0, 1 # are we done? 1212 bne v0, zero, 1b # no, continue 1213 sltu v0, zero, t9 # be sure to save any one bits 1214 or t8, t8, v0 # from the lower remainder 1215 b norm_d 1216 1217/* 1218 * Single precision absolute value. 1219 */ 1220abs_s: 1221 jal get_fs_s 1222 move t0, zero # set sign positive 1223 b result_fs_s 1224 1225/* 1226 * Double precision absolute value. 1227 */ 1228abs_d: 1229 jal get_fs_d 1230 move t0, zero # set sign positive 1231 b result_fs_d 1232 1233/* 1234 * Single precision move. 1235 */ 1236mov_s: 1237 jal get_fs_s 1238 b result_fs_s 1239 1240/* 1241 * Double precision move. 1242 */ 1243mov_d: 1244 jal get_fs_d 1245 b result_fs_d 1246 1247/* 1248 * Single precision negate. 1249 */ 1250neg_s: 1251 jal get_fs_s 1252 xor t0, t0, 1 # reverse sign 1253 b result_fs_s 1254 1255/* 1256 * Double precision negate. 1257 */ 1258neg_d: 1259 jal get_fs_d 1260 xor t0, t0, 1 # reverse sign 1261 b result_fs_d 1262 1263/* 1264 * Convert double to single. 1265 */ 1266cvt_s_d: 1267 jal get_fs_d 1268 bne t1, DEXP_INF, 1f # is FS an infinity? 1269 li t1, SEXP_INF # convert to single 1270 sll t2, t2, 3 # convert D fraction to S 1271 srl t8, t3, 32 - 3 1272 or t2, t2, t8 1273 b result_fs_s 12741: 1275 bne t1, zero, 2f # is FS zero? 1276 bne t2, zero, 1f 1277 beq t3, zero, result_fs_s # result=0 12781: 1279 jal renorm_fs_d 1280 subu t1, t1, 3 # correct exp for shift below 1281 b 3f 12822: 1283 subu t1, t1, DEXP_BIAS # unbias exponent 1284 or t2, t2, DIMPL_ONE # add implied one bit 12853: 1286 sll t2, t2, 3 # convert D fraction to S 1287 srl t8, t3, 32 - 3 1288 or t2, t2, t8 1289 sll t8, t3, 3 1290 b norm_noshift_s 1291 1292/* 1293 * Convert integer to single. 1294 */ 1295cvt_s_w: 1296 jal get_fs_int 1297 bne t2, zero, 1f # check for zero 1298 move t1, zero 1299 b result_fs_s 1300/* 1301 * Find out how many leading zero bits are in t2 and put in t9. 1302 */ 13031: 1304 move v0, t2 1305 move t9, zero 1306 srl v1, v0, 16 1307 bne v1, zero, 1f 1308 addu t9, 16 1309 sll v0, 16 13101: 1311 srl v1, v0, 24 1312 bne v1, zero, 1f 1313 addu t9, 8 1314 sll v0, 8 13151: 1316 srl v1, v0, 28 1317 bne v1, zero, 1f 1318 addu t9, 4 1319 sll v0, 4 13201: 1321 srl v1, v0, 30 1322 bne v1, zero, 1f 1323 addu t9, 2 1324 sll v0, 2 13251: 1326 srl v1, v0, 31 1327 bne v1, zero, 1f 1328 addu t9, 1 1329/* 1330 * Now shift t2 the correct number of bits. 1331 */ 13321: 1333 subu t9, t9, SLEAD_ZEROS # dont count leading zeros 1334 li t1, 23 # init exponent 1335 subu t1, t1, t9 # compute exponent 1336 beq t9, zero, 1f 1337 li v0, 32 1338 blt t9, zero, 2f # if shift < 0, shift right 1339 subu v0, v0, t9 1340 sll t2, t2, t9 # shift left 13411: 1342 add t1, t1, SEXP_BIAS # bias exponent 1343 and t2, t2, ~SIMPL_ONE # clear implied one bit 1344 b result_fs_s 13452: 1346 negu t9 # shift right by t9 1347 subu v0, v0, t9 1348 sll t8, t2, v0 # save bits shifted out 1349 srl t2, t2, t9 1350 b norm_noshift_s 1351 1352/* 1353 * Convert single to double. 1354 */ 1355cvt_d_s: 1356 jal get_fs_s 1357 move t3, zero 1358 bne t1, SEXP_INF, 1f # is FS an infinity? 1359 li t1, DEXP_INF # convert to double 1360 b result_fs_d 13611: 1362 bne t1, zero, 2f # is FS denormalized or zero? 1363 beq t2, zero, result_fs_d # is FS zero? 1364 jal renorm_fs_s 1365 move t8, zero 1366 b norm_d 13672: 1368 addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly 1369 sll t3, t2, 32 - 3 # convert S fraction to D 1370 srl t2, t2, 3 1371 b result_fs_d 1372 1373/* 1374 * Convert integer to double. 1375 */ 1376cvt_d_w: 1377 jal get_fs_int 1378 bne t2, zero, 1f # check for zero 1379 move t1, zero # result=0 1380 move t3, zero 1381 b result_fs_d 1382/* 1383 * Find out how many leading zero bits are in t2 and put in t9. 1384 */ 13851: 1386 move v0, t2 1387 move t9, zero 1388 srl v1, v0, 16 1389 bne v1, zero, 1f 1390 addu t9, 16 1391 sll v0, 16 13921: 1393 srl v1, v0, 24 1394 bne v1, zero, 1f 1395 addu t9, 8 1396 sll v0, 8 13971: 1398 srl v1, v0, 28 1399 bne v1, zero, 1f 1400 addu t9, 4 1401 sll v0, 4 14021: 1403 srl v1, v0, 30 1404 bne v1, zero, 1f 1405 addu t9, 2 1406 sll v0, 2 14071: 1408 srl v1, v0, 31 1409 bne v1, zero, 1f 1410 addu t9, 1 1411/* 1412 * Now shift t2 the correct number of bits. 1413 */ 14141: 1415 subu t9, t9, DLEAD_ZEROS # dont count leading zeros 1416 li t1, DEXP_BIAS + 20 # init exponent 1417 subu t1, t1, t9 # compute exponent 1418 beq t9, zero, 1f 1419 li v0, 32 1420 blt t9, zero, 2f # if shift < 0, shift right 1421 subu v0, v0, t9 1422 sll t2, t2, t9 # shift left 14231: 1424 and t2, t2, ~DIMPL_ONE # clear implied one bit 1425 move t3, zero 1426 b result_fs_d 14272: 1428 negu t9 # shift right by t9 1429 subu v0, v0, t9 1430 sll t3, t2, v0 1431 srl t2, t2, t9 1432 and t2, t2, ~DIMPL_ONE # clear implied one bit 1433 b result_fs_d 1434 1435/* 1436 * Convert single to integer. 1437 */ 1438cvt_w_s: 1439 jal get_fs_s 1440 bne t1, SEXP_INF, 1f # is FS an infinity? 1441 bne t2, zero, invalid_w # invalid conversion 14421: 1443 bne t1, zero, 1f # is FS zero? 1444 beq t2, zero, result_fs_w # result is zero 1445 move t2, zero # result is an inexact zero 1446 b inexact_w 14471: 1448 subu t1, t1, SEXP_BIAS # unbias exponent 1449 or t2, t2, SIMPL_ONE # add implied one bit 1450 sll t3, t2, 32 - 3 # convert S fraction to D 1451 srl t2, t2, 3 1452 b cvt_w 1453 1454/* 1455 * Convert double to integer. 1456 */ 1457cvt_w_d: 1458 jal get_fs_d 1459 bne t1, DEXP_INF, 1f # is FS an infinity? 1460 bne t2, zero, invalid_w # invalid conversion 1461 bne t3, zero, invalid_w # invalid conversion 14621: 1463 bne t1, zero, 2f # is FS zero? 1464 bne t2, zero, 1f 1465 beq t3, zero, result_fs_w # result is zero 14661: 1467 move t2, zero # result is an inexact zero 1468 b inexact_w 14692: 1470 subu t1, t1, DEXP_BIAS # unbias exponent 1471 or t2, t2, DIMPL_ONE # add implied one bit 1472cvt_w: 1473 blt t1, WEXP_MIN, underflow_w # is exponent too small? 1474 li v0, WEXP_MAX+1 1475 bgt t1, v0, overflow_w # is exponent too large? 1476 bne t1, v0, 1f # special check for INT_MIN 1477 beq t0, zero, overflow_w # if positive, overflow 1478 bne t2, DIMPL_ONE, overflow_w 1479 bne t3, zero, overflow_w 1480 li t2, INT_MIN # result is INT_MIN 1481 b result_fs_w 14821: 1483 subu v0, t1, 20 # compute amount to shift 1484 beq v0, zero, 2f # is shift needed? 1485 li v1, 32 1486 blt v0, zero, 1f # if shift < 0, shift right 1487 subu v1, v1, v0 # shift left 1488 sll t2, t2, v0 1489 srl t9, t3, v1 # save bits shifted out of t3 1490 or t2, t2, t9 # and put into t2 1491 sll t3, t3, v0 # shift FSs fraction 1492 b 2f 14931: 1494 negu v0 # shift right by v0 1495 subu v1, v1, v0 1496 sll t8, t3, v1 # save bits shifted out 1497 sltu t8, zero, t8 # dont lose any ones 1498 srl t3, t3, v0 # shift FSs fraction 1499 or t3, t3, t8 1500 sll t9, t2, v1 # save bits shifted out of t2 1501 or t3, t3, t9 # and put into t3 1502 srl t2, t2, v0 1503/* 1504 * round result (t0 is sign, t2 is integer part, t3 is fractional part). 1505 */ 15062: 1507 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 1508 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 1509 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 1510 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1511 beq t0, zero, 5f # if sign is positive, truncate 1512 b 2f 15131: 1514 bne t0, zero, 5f # if sign is negative, truncate 15152: 1516 beq t3, zero, 5f # if no fraction bits, continue 1517 addu t2, t2, 1 # add rounding bit 1518 blt t2, zero, overflow_w # overflow? 1519 b 5f 15203: 1521 li v0, GUARDBIT # load guard bit for rounding 1522 addu v0, v0, t3 # add remainder 1523 sltu v1, v0, t3 # compute carry out 1524 beq v1, zero, 4f # if no carry, continue 1525 addu t2, t2, 1 # add carry to result 1526 blt t2, zero, overflow_w # overflow? 15274: 1528 bne v0, zero, 5f # if rounded remainder is zero 1529 and t2, t2, ~1 # clear LSB (round to nearest) 15305: 1531 beq t0, zero, 1f # result positive? 1532 negu t2 # convert to negative integer 15331: 1534 beq t3, zero, result_fs_w # is result exact? 1535/* 1536 * Handle inexact exception. 1537 */ 1538inexact_w: 1539 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 1540 and v0, a1, MIPS_FPU_ENABLE_INEXACT 1541 bne v0, zero, fpe_trap 1542 ctc1 a1, MIPS_FPU_CSR # save exceptions 1543 b result_fs_w 1544 1545/* 1546 * Conversions to integer which overflow will trap (if enabled), 1547 * or generate an inexact trap (if enabled), 1548 * or generate an invalid exception. 1549 */ 1550overflow_w: 1551 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW 1552 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW 1553 bne v0, zero, fpe_trap 1554 and v0, a1, MIPS_FPU_ENABLE_INEXACT 1555 bne v0, zero, inexact_w # inexact traps enabled? 1556 b invalid_w 1557 1558/* 1559 * Conversions to integer which underflow will trap (if enabled), 1560 * or generate an inexact trap (if enabled), 1561 * or generate an invalid exception. 1562 */ 1563underflow_w: 1564 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 1565 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW 1566 bne v0, zero, fpe_trap 1567 and v0, a1, MIPS_FPU_ENABLE_INEXACT 1568 bne v0, zero, inexact_w # inexact traps enabled? 1569 b invalid_w 1570 1571/* 1572 * Compare single. 1573 */ 1574cmp_s: 1575 jal get_cmp_s 1576 bne t1, SEXP_INF, 1f # is FS an infinity? 1577 bne t2, zero, unordered # FS is a NAN 15781: 1579 bne ta1, SEXP_INF, 2f # is FT an infinity? 1580 bne ta2, zero, unordered # FT is a NAN 15812: 1582 sll t1, t1, 23 # reassemble exp & frac 1583 or t1, t1, t2 1584 sll ta1, ta1, 23 # reassemble exp & frac 1585 or ta1, ta1, ta2 1586 beq t0, zero, 1f # is FS positive? 1587 negu t1 15881: 1589 beq ta0, zero, 1f # is FT positive? 1590 negu ta1 15911: 1592 li v0, COND_LESS 1593 blt t1, ta1, test_cond # is FS < FT? 1594 li v0, COND_EQUAL 1595 beq t1, ta1, test_cond # is FS == FT? 1596 move v0, zero # FS > FT 1597 b test_cond 1598 1599/* 1600 * Compare double. 1601 */ 1602cmp_d: 1603 jal get_cmp_d 1604 bne t1, DEXP_INF, 1f # is FS an infinity? 1605 bne t2, zero, unordered 1606 bne t3, zero, unordered # FS is a NAN 16071: 1608 bne ta1, DEXP_INF, 2f # is FT an infinity? 1609 bne ta2, zero, unordered 1610 bne ta3, zero, unordered # FT is a NAN 16112: 1612 sll t1, t1, 20 # reassemble exp & frac 1613 or t1, t1, t2 1614 sll ta1, ta1, 20 # reassemble exp & frac 1615 or ta1, ta1, ta2 1616 beq t0, zero, 1f # is FS positive? 1617 not t3 # negate t1,t3 1618 not t1 1619 addu t3, t3, 1 1620 seq v0, t3, zero # compute carry 1621 addu t1, t1, v0 16221: 1623 beq ta0, zero, 1f # is FT positive? 1624 not ta3 # negate ta1,ta3 1625 not ta1 1626 addu ta3, ta3, 1 1627 seq v0, ta3, zero # compute carry 1628 addu ta1, ta1, v0 16291: 1630 li v0, COND_LESS 1631 blt t1, ta1, test_cond # is FS(MSW) < FT(MSW)? 1632 move v0, zero 1633 bne t1, ta1, test_cond # is FS(MSW) > FT(MSW)? 1634 li v0, COND_LESS 1635 bltu t3, ta3, test_cond # is FS(LSW) < FT(LSW)? 1636 li v0, COND_EQUAL 1637 beq t3, ta3, test_cond # is FS(LSW) == FT(LSW)? 1638 move v0, zero # FS > FT 1639test_cond: 1640 and v0, v0, a0 # condition match instruction? 1641set_cond: 1642 bne v0, zero, 1f 1643 and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit 1644 b 2f 16451: 1646 or a1, a1, MIPS_FPU_COND_BIT # set condition bit 16472: 1648 ctc1 a1, MIPS_FPU_CSR # save condition bit 1649 b done 1650 1651unordered: 1652 and v0, a0, COND_UNORDERED # this cmp match unordered? 1653 bne v0, zero, 1f 1654 and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit 1655 b 2f 16561: 1657 or a1, a1, MIPS_FPU_COND_BIT # set condition bit 16582: 1659 and v0, a0, COND_SIGNAL 1660 beq v0, zero, 1f # is this a signaling cmp? 1661 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 1662 and v0, a1, MIPS_FPU_ENABLE_INVALID 1663 bne v0, zero, fpe_trap 16641: 1665 ctc1 a1, MIPS_FPU_CSR # save condition bit 1666 b done 1667 1668/* 1669 * Determine the amount to shift the fraction in order to restore the 1670 * normalized position. After that, round and handle exceptions. 1671 */ 1672norm_s: 1673 move v0, t2 1674 move t9, zero # t9 = num of leading zeros 1675 bne t2, zero, 1f 1676 move v0, t8 1677 addu t9, 32 16781: 1679 srl v1, v0, 16 1680 bne v1, zero, 1f 1681 addu t9, 16 1682 sll v0, 16 16831: 1684 srl v1, v0, 24 1685 bne v1, zero, 1f 1686 addu t9, 8 1687 sll v0, 8 16881: 1689 srl v1, v0, 28 1690 bne v1, zero, 1f 1691 addu t9, 4 1692 sll v0, 4 16931: 1694 srl v1, v0, 30 1695 bne v1, zero, 1f 1696 addu t9, 2 1697 sll v0, 2 16981: 1699 srl v1, v0, 31 1700 bne v1, zero, 1f 1701 addu t9, 1 1702/* 1703 * Now shift t2,t8 the correct number of bits. 1704 */ 17051: 1706 subu t9, t9, SLEAD_ZEROS # dont count leading zeros 1707 subu t1, t1, t9 # adjust the exponent 1708 beq t9, zero, norm_noshift_s 1709 li v1, 32 1710 blt t9, zero, 1f # if shift < 0, shift right 1711 subu v1, v1, t9 1712 sll t2, t2, t9 # shift t2,t8 left 1713 srl v0, t8, v1 # save bits shifted out 1714 or t2, t2, v0 1715 sll t8, t8, t9 1716 b norm_noshift_s 17171: 1718 negu t9 # shift t2,t8 right by t9 1719 subu v1, v1, t9 1720 sll v0, t8, v1 # save bits shifted out 1721 sltu v0, zero, v0 # be sure to save any one bits 1722 srl t8, t8, t9 1723 or t8, t8, v0 1724 sll v0, t2, v1 # save bits shifted out 1725 or t8, t8, v0 1726 srl t2, t2, t9 1727norm_noshift_s: 1728 move ta1, t1 # save unrounded exponent 1729 move ta2, t2 # save unrounded fraction 1730 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 1731 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 1732 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 1733 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1734 beq t0, zero, 5f # if sign is positive, truncate 1735 b 2f 17361: 1737 bne t0, zero, 5f # if sign is negative, truncate 17382: 1739 beq t8, zero, 5f # if exact, continue 1740 addu t2, t2, 1 # add rounding bit 1741 bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent? 1742 addu t1, t1, 1 # adjust exponent 1743 srl t2, t2, 1 # renormalize fraction 1744 b 5f 17453: 1746 li v0, GUARDBIT # load guard bit for rounding 1747 addu v0, v0, t8 # add remainder 1748 sltu v1, v0, t8 # compute carry out 1749 beq v1, zero, 4f # if no carry, continue 1750 addu t2, t2, 1 # add carry to result 1751 bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent? 1752 addu t1, t1, 1 # adjust exponent 1753 srl t2, t2, 1 # renormalize fraction 17544: 1755 bne v0, zero, 5f # if rounded remainder is zero 1756 and t2, t2, ~1 # clear LSB (round to nearest) 17575: 1758 bgt t1, SEXP_MAX, overflow_s # overflow? 1759 blt t1, SEXP_MIN, underflow_s # underflow? 1760 bne t8, zero, inexact_s # is result inexact? 1761 addu t1, t1, SEXP_BIAS # bias exponent 1762 and t2, t2, ~SIMPL_ONE # clear implied one bit 1763 b result_fs_s 1764 1765/* 1766 * Handle inexact exception. 1767 */ 1768inexact_s: 1769 addu t1, t1, SEXP_BIAS # bias exponent 1770 and t2, t2, ~SIMPL_ONE # clear implied one bit 1771inexact_nobias_s: 1772 jal set_fd_s # save result 1773 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 1774 and v0, a1, MIPS_FPU_ENABLE_INEXACT 1775 bne v0, zero, fpe_trap 1776 ctc1 a1, MIPS_FPU_CSR # save exceptions 1777 b done 1778 1779/* 1780 * Overflow will trap (if enabled), 1781 * or generate an inexact trap (if enabled), 1782 * or generate an infinity. 1783 */ 1784overflow_s: 1785 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW 1786 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW 1787 beq v0, zero, 1f 1788 subu t1, t1, 192 # bias exponent 1789 and t2, t2, ~SIMPL_ONE # clear implied one bit 1790 jal set_fd_s # save result 1791 b fpe_trap 17921: 1793 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 1794 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 1795 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate) 1796 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity 1797 bne t0, zero, 3f 17981: 1799 li t1, SEXP_MAX # result is max finite 1800 li t2, 0x007fffff 1801 b inexact_s 18022: 1803 bne t0, zero, 1b 18043: 1805 li t1, SEXP_MAX + 1 # result is infinity 1806 move t2, zero 1807 b inexact_s 1808 1809/* 1810 * In this implementation, "tininess" is detected "after rounding" and 1811 * "loss of accuracy" is detected as "an inexact result". 1812 */ 1813underflow_s: 1814 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW 1815 beq v0, zero, 1f 1816/* 1817 * Underflow is enabled so compute the result and trap. 1818 */ 1819 addu t1, t1, 192 # bias exponent 1820 and t2, t2, ~SIMPL_ONE # clear implied one bit 1821 jal set_fd_s # save result 1822 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 1823 b fpe_trap 1824/* 1825 * Underflow is not enabled so compute the result, 1826 * signal inexact result (if it is) and trap (if enabled). 1827 */ 18281: 1829 move t1, ta1 # get unrounded exponent 1830 move t2, ta2 # get unrounded fraction 1831 li t9, SEXP_MIN # compute shift amount 1832 subu t9, t9, t1 # shift t2,t8 right by t9 1833 blt t9, SFRAC_BITS+2, 3f # shift all the bits out? 1834 move t1, zero # result is inexact zero 1835 move t2, zero 1836 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 1837/* 1838 * Now round the zero result. 1839 * Only need to worry about rounding to +- infinity when the sign matches. 1840 */ 1841 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 1842 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest 1843 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero 1844 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1845 beq t0, zero, inexact_nobias_s # if sign is positive, truncate 1846 b 2f 18471: 1848 bne t0, zero, inexact_nobias_s # if sign is negative, truncate 18492: 1850 addu t2, t2, 1 # add rounding bit 1851 b inexact_nobias_s 18523: 1853 li v1, 32 1854 subu v1, v1, t9 1855 sltu v0, zero, t8 # be sure to save any one bits 1856 sll t8, t2, v1 # save bits shifted out 1857 or t8, t8, v0 # include sticky bits 1858 srl t2, t2, t9 1859/* 1860 * Now round the denormalized result. 1861 */ 1862 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 1863 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 1864 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 1865 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1866 beq t0, zero, 5f # if sign is positive, truncate 1867 b 2f 18681: 1869 bne t0, zero, 5f # if sign is negative, truncate 18702: 1871 beq t8, zero, 5f # if exact, continue 1872 addu t2, t2, 1 # add rounding bit 1873 b 5f 18743: 1875 li v0, GUARDBIT # load guard bit for rounding 1876 addu v0, v0, t8 # add remainder 1877 sltu v1, v0, t8 # compute carry out 1878 beq v1, zero, 4f # if no carry, continue 1879 addu t2, t2, 1 # add carry to result 18804: 1881 bne v0, zero, 5f # if rounded remainder is zero 1882 and t2, t2, ~1 # clear LSB (round to nearest) 18835: 1884 move t1, zero # denorm or zero exponent 1885 jal set_fd_s # save result 1886 beq t8, zero, done # check for exact result 1887 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 1888 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 1889 and v0, a1, MIPS_FPU_ENABLE_INEXACT 1890 bne v0, zero, fpe_trap 1891 ctc1 a1, MIPS_FPU_CSR # save exceptions 1892 b done 1893 1894/* 1895 * Determine the amount to shift the fraction in order to restore the 1896 * normalized position. After that, round and handle exceptions. 1897 */ 1898norm_d: 1899 move v0, t2 1900 move t9, zero # t9 = num of leading zeros 1901 bne t2, zero, 1f 1902 move v0, t3 1903 addu t9, 32 1904 bne t3, zero, 1f 1905 move v0, t8 1906 addu t9, 32 19071: 1908 srl v1, v0, 16 1909 bne v1, zero, 1f 1910 addu t9, 16 1911 sll v0, 16 19121: 1913 srl v1, v0, 24 1914 bne v1, zero, 1f 1915 addu t9, 8 1916 sll v0, 8 19171: 1918 srl v1, v0, 28 1919 bne v1, zero, 1f 1920 addu t9, 4 1921 sll v0, 4 19221: 1923 srl v1, v0, 30 1924 bne v1, zero, 1f 1925 addu t9, 2 1926 sll v0, 2 19271: 1928 srl v1, v0, 31 1929 bne v1, zero, 1f 1930 addu t9, 1 1931/* 1932 * Now shift t2,t3,t8 the correct number of bits. 1933 */ 19341: 1935 subu t9, t9, DLEAD_ZEROS # dont count leading zeros 1936 subu t1, t1, t9 # adjust the exponent 1937 beq t9, zero, norm_noshift_d 1938 li v1, 32 1939 blt t9, zero, 2f # if shift < 0, shift right 1940 blt t9, v1, 1f # shift by < 32? 1941 subu t9, t9, v1 # shift by >= 32 1942 subu v1, v1, t9 1943 sll t2, t3, t9 # shift left by t9 1944 srl v0, t8, v1 # save bits shifted out 1945 or t2, t2, v0 1946 sll t3, t8, t9 1947 move t8, zero 1948 b norm_noshift_d 19491: 1950 subu v1, v1, t9 1951 sll t2, t2, t9 # shift left by t9 1952 srl v0, t3, v1 # save bits shifted out 1953 or t2, t2, v0 1954 sll t3, t3, t9 1955 srl v0, t8, v1 # save bits shifted out 1956 or t3, t3, v0 1957 sll t8, t8, t9 1958 b norm_noshift_d 19592: 1960 negu t9 # shift right by t9 1961 subu v1, v1, t9 # (known to be < 32 bits) 1962 sll v0, t8, v1 # save bits shifted out 1963 sltu v0, zero, v0 # be sure to save any one bits 1964 srl t8, t8, t9 1965 or t8, t8, v0 1966 sll v0, t3, v1 # save bits shifted out 1967 or t8, t8, v0 1968 srl t3, t3, t9 1969 sll v0, t2, v1 # save bits shifted out 1970 or t3, t3, v0 1971 srl t2, t2, t9 1972norm_noshift_d: 1973 move ta1, t1 # save unrounded exponent 1974 move ta2, t2 # save unrounded fraction (MS) 1975 move ta3, t3 # save unrounded fraction (LS) 1976 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 1977 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 1978 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 1979 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1980 beq t0, zero, 5f # if sign is positive, truncate 1981 b 2f 19821: 1983 bne t0, zero, 5f # if sign is negative, truncate 19842: 1985 beq t8, zero, 5f # if exact, continue 1986 addu t3, t3, 1 # add rounding bit 1987 bne t3, zero, 5f # branch if no carry 1988 addu t2, t2, 1 # add carry 1989 bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent? 1990 addu t1, t1, 1 # adjust exponent 1991 srl t2, t2, 1 # renormalize fraction 1992 b 5f 19933: 1994 li v0, GUARDBIT # load guard bit for rounding 1995 addu v0, v0, t8 # add remainder 1996 sltu v1, v0, t8 # compute carry out 1997 beq v1, zero, 4f # branch if no carry 1998 addu t3, t3, 1 # add carry 1999 bne t3, zero, 4f # branch if no carry 2000 addu t2, t2, 1 # add carry to result 2001 bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent? 2002 addu t1, t1, 1 # adjust exponent 2003 srl t2, t2, 1 # renormalize fraction 20044: 2005 bne v0, zero, 5f # if rounded remainder is zero 2006 and t3, t3, ~1 # clear LSB (round to nearest) 20075: 2008 bgt t1, DEXP_MAX, overflow_d # overflow? 2009 blt t1, DEXP_MIN, underflow_d # underflow? 2010 bne t8, zero, inexact_d # is result inexact? 2011 addu t1, t1, DEXP_BIAS # bias exponent 2012 and t2, t2, ~DIMPL_ONE # clear implied one bit 2013 b result_fs_d 2014 2015/* 2016 * Handle inexact exception. 2017 */ 2018inexact_d: 2019 addu t1, t1, DEXP_BIAS # bias exponent 2020 and t2, t2, ~DIMPL_ONE # clear implied one bit 2021inexact_nobias_d: 2022 jal set_fd_d # save result 2023 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 2024 and v0, a1, MIPS_FPU_ENABLE_INEXACT 2025 bne v0, zero, fpe_trap 2026 ctc1 a1, MIPS_FPU_CSR # save exceptions 2027 b done 2028 2029/* 2030 * Overflow will trap (if enabled), 2031 * or generate an inexact trap (if enabled), 2032 * or generate an infinity. 2033 */ 2034overflow_d: 2035 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW 2036 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW 2037 beq v0, zero, 1f 2038 subu t1, t1, 1536 # bias exponent 2039 and t2, t2, ~DIMPL_ONE # clear implied one bit 2040 jal set_fd_d # save result 2041 b fpe_trap 20421: 2043 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 2044 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2045 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate) 2046 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity 2047 bne t0, zero, 3f 20481: 2049 li t1, DEXP_MAX # result is max finite 2050 li t2, 0x000fffff 2051 li t3, 0xffffffff 2052 b inexact_d 20532: 2054 bne t0, zero, 1b 20553: 2056 li t1, DEXP_MAX + 1 # result is infinity 2057 move t2, zero 2058 move t3, zero 2059 b inexact_d 2060 2061/* 2062 * In this implementation, "tininess" is detected "after rounding" and 2063 * "loss of accuracy" is detected as "an inexact result". 2064 */ 2065underflow_d: 2066 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW 2067 beq v0, zero, 1f 2068/* 2069 * Underflow is enabled so compute the result and trap. 2070 */ 2071 addu t1, t1, 1536 # bias exponent 2072 and t2, t2, ~DIMPL_ONE # clear implied one bit 2073 jal set_fd_d # save result 2074 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2075 b fpe_trap 2076/* 2077 * Underflow is not enabled so compute the result, 2078 * signal inexact result (if it is) and trap (if enabled). 2079 */ 20801: 2081 move t1, ta1 # get unrounded exponent 2082 move t2, ta2 # get unrounded fraction (MS) 2083 move t3, ta3 # get unrounded fraction (LS) 2084 li t9, DEXP_MIN # compute shift amount 2085 subu t9, t9, t1 # shift t2,t8 right by t9 2086 blt t9, DFRAC_BITS+2, 3f # shift all the bits out? 2087 move t1, zero # result is inexact zero 2088 move t2, zero 2089 move t3, zero 2090 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2091/* 2092 * Now round the zero result. 2093 * Only need to worry about rounding to +- infinity when the sign matches. 2094 */ 2095 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 2096 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_d # round to nearest 2097 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d # round to zero 2098 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2099 beq t0, zero, inexact_nobias_d # if sign is positive, truncate 2100 b 2f 21011: 2102 bne t0, zero, inexact_nobias_d # if sign is negative, truncate 21032: 2104 addu t3, t3, 1 # add rounding bit 2105 b inexact_nobias_d 21063: 2107 li v1, 32 2108 blt t9, v1, 1f # shift by < 32? 2109 subu t9, t9, v1 # shift right by >= 32 2110 subu v1, v1, t9 2111 sltu v0, zero, t8 # be sure to save any one bits 2112 sll t8, t2, v1 # save bits shifted out 2113 or t8, t8, v0 # include sticky bits 2114 srl t3, t2, t9 2115 move t2, zero 2116 b 2f 21171: 2118 subu v1, v1, t9 # shift right by t9 2119 sltu v0, zero, t8 # be sure to save any one bits 2120 sll t8, t3, v1 # save bits shifted out 2121 or t8, t8, v0 # include sticky bits 2122 srl t3, t3, t9 2123 sll v0, t2, v1 # save bits shifted out 2124 or t3, t3, v0 2125 srl t2, t2, t9 2126/* 2127 * Now round the denormalized result. 2128 */ 21292: 2130 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode 2131 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2132 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 2133 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2134 beq t0, zero, 5f # if sign is positive, truncate 2135 b 2f 21361: 2137 bne t0, zero, 5f # if sign is negative, truncate 21382: 2139 beq t8, zero, 5f # if exact, continue 2140 addu t3, t3, 1 # add rounding bit 2141 bne t3, zero, 5f # if no carry, continue 2142 addu t2, t2, 1 # add carry 2143 b 5f 21443: 2145 li v0, GUARDBIT # load guard bit for rounding 2146 addu v0, v0, t8 # add remainder 2147 sltu v1, v0, t8 # compute carry out 2148 beq v1, zero, 4f # if no carry, continue 2149 addu t3, t3, 1 # add rounding bit 2150 bne t3, zero, 4f # if no carry, continue 2151 addu t2, t2, 1 # add carry 21524: 2153 bne v0, zero, 5f # if rounded remainder is zero 2154 and t3, t3, ~1 # clear LSB (round to nearest) 21555: 2156 move t1, zero # denorm or zero exponent 2157 jal set_fd_d # save result 2158 beq t8, zero, done # check for exact result 2159 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2160 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 2161 and v0, a1, MIPS_FPU_ENABLE_INEXACT 2162 bne v0, zero, fpe_trap 2163 ctc1 a1, MIPS_FPU_CSR # save exceptions 2164 b done 2165 2166/* 2167 * Signal an invalid operation if the trap is enabled; otherwise, 2168 * the result is a quiet NAN. 2169 */ 2170invalid_s: # trap invalid operation 2171 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 2172 and v0, a1, MIPS_FPU_ENABLE_INVALID 2173 bne v0, zero, fpe_trap 2174 ctc1 a1, MIPS_FPU_CSR # save exceptions 2175 move t0, zero # result is a quiet NAN 2176 li t1, SEXP_INF 2177 li t2, SQUIET_NAN 2178 jal set_fd_s # save result (in t0,t1,t2) 2179 b done 2180 2181/* 2182 * Signal an invalid operation if the trap is enabled; otherwise, 2183 * the result is a quiet NAN. 2184 */ 2185invalid_d: # trap invalid operation 2186 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 2187 and v0, a1, MIPS_FPU_ENABLE_INVALID 2188 bne v0, zero, fpe_trap 2189 ctc1 a1, MIPS_FPU_CSR # save exceptions 2190 move t0, zero # result is a quiet NAN 2191 li t1, DEXP_INF 2192 li t2, DQUIET_NAN0 2193 li t3, DQUIET_NAN1 2194 jal set_fd_d # save result (in t0,t1,t2,t3) 2195 b done 2196 2197/* 2198 * Signal an invalid operation if the trap is enabled; otherwise, 2199 * the result is INT_MAX or INT_MIN. 2200 */ 2201invalid_w: # trap invalid operation 2202 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 2203 and v0, a1, MIPS_FPU_ENABLE_INVALID 2204 bne v0, zero, fpe_trap 2205 ctc1 a1, MIPS_FPU_CSR # save exceptions 2206 bne t0, zero, 1f 2207 li t2, INT_MAX # result is INT_MAX 2208 b result_fs_w 22091: 2210 li t2, INT_MIN # result is INT_MIN 2211 b result_fs_w 2212 2213/* 2214 * Trap if the hardware should have handled this case. 2215 */ 2216fpe_trap: 2217 move a2, a1 # code = FP CSR 2218 ctc1 a1, MIPS_FPU_CSR # save exceptions 2219 break 0 2220 2221/* 2222 * Send an illegal instruction signal to the current process. 2223 */ 2224ill: 2225 ctc1 a1, MIPS_FPU_CSR # save exceptions 2226 move a2, a0 # code = FP instruction 2227 break 0 2228 2229result_ft_s: 2230 move t0, ta0 # result is FT 2231 move t1, ta1 2232 move t2, ta2 2233result_fs_s: # result is FS 2234 jal set_fd_s # save result (in t0,t1,t2) 2235 b done 2236 2237result_fs_w: 2238 jal set_fd_word # save result (in t2) 2239 b done 2240 2241result_ft_d: 2242 move t0, ta0 # result is FT 2243 move t1, ta1 2244 move t2, ta2 2245 move t3, ta3 2246result_fs_d: # result is FS 2247 jal set_fd_d # save result (in t0,t1,t2,t3) 2248 2249done: 2250 lw ra, CALLFRAME_RA(sp) 2251 addu sp, sp, CALLFRAME_SIZ 2252 j ra 2253END(MipsEmulateFP) 2254 2255/*---------------------------------------------------------------------------- 2256 * get_fs_int -- 2257 * 2258 * Read (integer) the FS register (bits 15-11). 2259 * This is an internal routine used by MipsEmulateFP only. 2260 * 2261 * Results: 2262 * t0 contains the sign 2263 * t2 contains the fraction 2264 * 2265 *---------------------------------------------------------------------------- 2266 */ 2267LEAF(get_fs_int) 2268 srl a3, a0, 12 - 2 # get FS field (even regs only) 2269 and a3, a3, 0xF << 2 # mask FS field 2270 lw a3, get_fs_int_tbl(a3) # switch on register number 2271 j a3 2272 2273 .rdata 2274get_fs_int_tbl: 2275 .word get_fs_int_f0 2276 .word get_fs_int_f2 2277 .word get_fs_int_f4 2278 .word get_fs_int_f6 2279 .word get_fs_int_f8 2280 .word get_fs_int_f10 2281 .word get_fs_int_f12 2282 .word get_fs_int_f14 2283 .word get_fs_int_f16 2284 .word get_fs_int_f18 2285 .word get_fs_int_f20 2286 .word get_fs_int_f22 2287 .word get_fs_int_f24 2288 .word get_fs_int_f26 2289 .word get_fs_int_f28 2290 .word get_fs_int_f30 2291 .text 2292 2293get_fs_int_f0: 2294 mfc1 t2, $f0 2295 b get_fs_int_done 2296get_fs_int_f2: 2297 mfc1 t2, $f2 2298 b get_fs_int_done 2299get_fs_int_f4: 2300 mfc1 t2, $f4 2301 b get_fs_int_done 2302get_fs_int_f6: 2303 mfc1 t2, $f6 2304 b get_fs_int_done 2305get_fs_int_f8: 2306 mfc1 t2, $f8 2307 b get_fs_int_done 2308get_fs_int_f10: 2309 mfc1 t2, $f10 2310 b get_fs_int_done 2311get_fs_int_f12: 2312 mfc1 t2, $f12 2313 b get_fs_int_done 2314get_fs_int_f14: 2315 mfc1 t2, $f14 2316 b get_fs_int_done 2317get_fs_int_f16: 2318 mfc1 t2, $f16 2319 b get_fs_int_done 2320get_fs_int_f18: 2321 mfc1 t2, $f18 2322 b get_fs_int_done 2323get_fs_int_f20: 2324 mfc1 t2, $f20 2325 b get_fs_int_done 2326get_fs_int_f22: 2327 mfc1 t2, $f22 2328 b get_fs_int_done 2329get_fs_int_f24: 2330 mfc1 t2, $f24 2331 b get_fs_int_done 2332get_fs_int_f26: 2333 mfc1 t2, $f26 2334 b get_fs_int_done 2335get_fs_int_f28: 2336 mfc1 t2, $f28 2337 b get_fs_int_done 2338get_fs_int_f30: 2339 mfc1 t2, $f30 2340get_fs_int_done: 2341 srl t0, t2, 31 # init the sign bit 2342 bge t2, zero, 1f 2343 negu t2 23441: 2345 j ra 2346END(get_fs_int) 2347 2348/*---------------------------------------------------------------------------- 2349 * get_ft_fs_s -- 2350 * 2351 * Read (single precision) the FT register (bits 20-16) and 2352 * the FS register (bits 15-11) and break up into fields. 2353 * This is an internal routine used by MipsEmulateFP only. 2354 * 2355 * Results: 2356 * t0 contains the FS sign 2357 * t1 contains the FS (biased) exponent 2358 * t2 contains the FS fraction 2359 * ta0 contains the FT sign 2360 * ta1 contains the FT (biased) exponent 2361 * ta2 contains the FT fraction 2362 * 2363 *---------------------------------------------------------------------------- 2364 */ 2365LEAF(get_ft_fs_s) 2366 srl a3, a0, 17 - 2 # get FT field (even regs only) 2367 and a3, a3, 0xF << 2 # mask FT field 2368 lw a3, get_ft_s_tbl(a3) # switch on register number 2369 j a3 2370 2371 .rdata 2372get_ft_s_tbl: 2373 .word get_ft_s_f0 2374 .word get_ft_s_f2 2375 .word get_ft_s_f4 2376 .word get_ft_s_f6 2377 .word get_ft_s_f8 2378 .word get_ft_s_f10 2379 .word get_ft_s_f12 2380 .word get_ft_s_f14 2381 .word get_ft_s_f16 2382 .word get_ft_s_f18 2383 .word get_ft_s_f20 2384 .word get_ft_s_f22 2385 .word get_ft_s_f24 2386 .word get_ft_s_f26 2387 .word get_ft_s_f28 2388 .word get_ft_s_f30 2389 .text 2390 2391get_ft_s_f0: 2392 mfc1 ta0, $f0 2393 b get_ft_s_done 2394get_ft_s_f2: 2395 mfc1 ta0, $f2 2396 b get_ft_s_done 2397get_ft_s_f4: 2398 mfc1 ta0, $f4 2399 b get_ft_s_done 2400get_ft_s_f6: 2401 mfc1 ta0, $f6 2402 b get_ft_s_done 2403get_ft_s_f8: 2404 mfc1 ta0, $f8 2405 b get_ft_s_done 2406get_ft_s_f10: 2407 mfc1 ta0, $f10 2408 b get_ft_s_done 2409get_ft_s_f12: 2410 mfc1 ta0, $f12 2411 b get_ft_s_done 2412get_ft_s_f14: 2413 mfc1 ta0, $f14 2414 b get_ft_s_done 2415get_ft_s_f16: 2416 mfc1 ta0, $f16 2417 b get_ft_s_done 2418get_ft_s_f18: 2419 mfc1 ta0, $f18 2420 b get_ft_s_done 2421get_ft_s_f20: 2422 mfc1 ta0, $f20 2423 b get_ft_s_done 2424get_ft_s_f22: 2425 mfc1 ta0, $f22 2426 b get_ft_s_done 2427get_ft_s_f24: 2428 mfc1 ta0, $f24 2429 b get_ft_s_done 2430get_ft_s_f26: 2431 mfc1 ta0, $f26 2432 b get_ft_s_done 2433get_ft_s_f28: 2434 mfc1 ta0, $f28 2435 b get_ft_s_done 2436get_ft_s_f30: 2437 mfc1 ta0, $f30 2438get_ft_s_done: 2439 srl ta1, ta0, 23 # get exponent 2440 and ta1, ta1, 0xFF 2441 and ta2, ta0, 0x7FFFFF # get fraction 2442 srl ta0, ta0, 31 # get sign 2443 bne ta1, SEXP_INF, 1f # is it a signaling NAN? 2444 and v0, ta2, SSIGNAL_NAN 2445 bne v0, zero, invalid_s 24461: 2447 /* fall through to get FS */ 2448 2449/*---------------------------------------------------------------------------- 2450 * get_fs_s -- 2451 * 2452 * Read (single precision) the FS register (bits 15-11) and 2453 * break up into fields. 2454 * This is an internal routine used by MipsEmulateFP only. 2455 * 2456 * Results: 2457 * t0 contains the sign 2458 * t1 contains the (biased) exponent 2459 * t2 contains the fraction 2460 * 2461 *---------------------------------------------------------------------------- 2462 */ 2463ALEAF(get_fs_s) 2464 srl a3, a0, 12 - 2 # get FS field (even regs only) 2465 and a3, a3, 0xF << 2 # mask FS field 2466 lw a3, get_fs_s_tbl(a3) # switch on register number 2467 j a3 2468 2469 .rdata 2470get_fs_s_tbl: 2471 .word get_fs_s_f0 2472 .word get_fs_s_f2 2473 .word get_fs_s_f4 2474 .word get_fs_s_f6 2475 .word get_fs_s_f8 2476 .word get_fs_s_f10 2477 .word get_fs_s_f12 2478 .word get_fs_s_f14 2479 .word get_fs_s_f16 2480 .word get_fs_s_f18 2481 .word get_fs_s_f20 2482 .word get_fs_s_f22 2483 .word get_fs_s_f24 2484 .word get_fs_s_f26 2485 .word get_fs_s_f28 2486 .word get_fs_s_f30 2487 .text 2488 2489get_fs_s_f0: 2490 mfc1 t0, $f0 2491 b get_fs_s_done 2492get_fs_s_f2: 2493 mfc1 t0, $f2 2494 b get_fs_s_done 2495get_fs_s_f4: 2496 mfc1 t0, $f4 2497 b get_fs_s_done 2498get_fs_s_f6: 2499 mfc1 t0, $f6 2500 b get_fs_s_done 2501get_fs_s_f8: 2502 mfc1 t0, $f8 2503 b get_fs_s_done 2504get_fs_s_f10: 2505 mfc1 t0, $f10 2506 b get_fs_s_done 2507get_fs_s_f12: 2508 mfc1 t0, $f12 2509 b get_fs_s_done 2510get_fs_s_f14: 2511 mfc1 t0, $f14 2512 b get_fs_s_done 2513get_fs_s_f16: 2514 mfc1 t0, $f16 2515 b get_fs_s_done 2516get_fs_s_f18: 2517 mfc1 t0, $f18 2518 b get_fs_s_done 2519get_fs_s_f20: 2520 mfc1 t0, $f20 2521 b get_fs_s_done 2522get_fs_s_f22: 2523 mfc1 t0, $f22 2524 b get_fs_s_done 2525get_fs_s_f24: 2526 mfc1 t0, $f24 2527 b get_fs_s_done 2528get_fs_s_f26: 2529 mfc1 t0, $f26 2530 b get_fs_s_done 2531get_fs_s_f28: 2532 mfc1 t0, $f28 2533 b get_fs_s_done 2534get_fs_s_f30: 2535 mfc1 t0, $f30 2536get_fs_s_done: 2537 srl t1, t0, 23 # get exponent 2538 and t1, t1, 0xFF 2539 and t2, t0, 0x7FFFFF # get fraction 2540 srl t0, t0, 31 # get sign 2541 bne t1, SEXP_INF, 1f # is it a signaling NAN? 2542 and v0, t2, SSIGNAL_NAN 2543 bne v0, zero, invalid_s 25441: 2545 j ra 2546END(get_ft_fs_s) 2547 2548/*---------------------------------------------------------------------------- 2549 * get_ft_fs_d -- 2550 * 2551 * Read (double precision) the FT register (bits 20-16) and 2552 * the FS register (bits 15-11) and break up into fields. 2553 * This is an internal routine used by MipsEmulateFP only. 2554 * 2555 * Results: 2556 * t0 contains the FS sign 2557 * t1 contains the FS (biased) exponent 2558 * t2 contains the FS fraction 2559 * t3 contains the FS remaining fraction 2560 * ta0 contains the FT sign 2561 * ta1 contains the FT (biased) exponent 2562 * ta2 contains the FT fraction 2563 * ta3 contains the FT remaining fraction 2564 * 2565 *---------------------------------------------------------------------------- 2566 */ 2567LEAF(get_ft_fs_d) 2568 srl a3, a0, 17 - 2 # get FT field (even regs only) 2569 and a3, a3, 0xF << 2 # mask FT field 2570 lw a3, get_ft_d_tbl(a3) # switch on register number 2571 j a3 2572 2573 .rdata 2574get_ft_d_tbl: 2575 .word get_ft_d_f0 2576 .word get_ft_d_f2 2577 .word get_ft_d_f4 2578 .word get_ft_d_f6 2579 .word get_ft_d_f8 2580 .word get_ft_d_f10 2581 .word get_ft_d_f12 2582 .word get_ft_d_f14 2583 .word get_ft_d_f16 2584 .word get_ft_d_f18 2585 .word get_ft_d_f20 2586 .word get_ft_d_f22 2587 .word get_ft_d_f24 2588 .word get_ft_d_f26 2589 .word get_ft_d_f28 2590 .word get_ft_d_f30 2591 .text 2592 2593get_ft_d_f0: 2594 mfc1 ta3, $f0 2595 mfc1 ta0, $f1 2596 b get_ft_d_done 2597get_ft_d_f2: 2598 mfc1 ta3, $f2 2599 mfc1 ta0, $f3 2600 b get_ft_d_done 2601get_ft_d_f4: 2602 mfc1 ta3, $f4 2603 mfc1 ta0, $f5 2604 b get_ft_d_done 2605get_ft_d_f6: 2606 mfc1 ta3, $f6 2607 mfc1 ta0, $f7 2608 b get_ft_d_done 2609get_ft_d_f8: 2610 mfc1 ta3, $f8 2611 mfc1 ta0, $f9 2612 b get_ft_d_done 2613get_ft_d_f10: 2614 mfc1 ta3, $f10 2615 mfc1 ta0, $f11 2616 b get_ft_d_done 2617get_ft_d_f12: 2618 mfc1 ta3, $f12 2619 mfc1 ta0, $f13 2620 b get_ft_d_done 2621get_ft_d_f14: 2622 mfc1 ta3, $f14 2623 mfc1 ta0, $f15 2624 b get_ft_d_done 2625get_ft_d_f16: 2626 mfc1 ta3, $f16 2627 mfc1 ta0, $f17 2628 b get_ft_d_done 2629get_ft_d_f18: 2630 mfc1 ta3, $f18 2631 mfc1 ta0, $f19 2632 b get_ft_d_done 2633get_ft_d_f20: 2634 mfc1 ta3, $f20 2635 mfc1 ta0, $f21 2636 b get_ft_d_done 2637get_ft_d_f22: 2638 mfc1 ta3, $f22 2639 mfc1 ta0, $f23 2640 b get_ft_d_done 2641get_ft_d_f24: 2642 mfc1 ta3, $f24 2643 mfc1 ta0, $f25 2644 b get_ft_d_done 2645get_ft_d_f26: 2646 mfc1 ta3, $f26 2647 mfc1 ta0, $f27 2648 b get_ft_d_done 2649get_ft_d_f28: 2650 mfc1 ta3, $f28 2651 mfc1 ta0, $f29 2652 b get_ft_d_done 2653get_ft_d_f30: 2654 mfc1 ta3, $f30 2655 mfc1 ta0, $f31 2656get_ft_d_done: 2657 srl ta1, ta0, 20 # get exponent 2658 and ta1, ta1, 0x7FF 2659 and ta2, ta0, 0xFFFFF # get fraction 2660 srl ta0, ta0, 31 # get sign 2661 bne ta1, DEXP_INF, 1f # is it a signaling NAN? 2662 and v0, ta2, DSIGNAL_NAN 2663 bne v0, zero, invalid_d 26641: 2665 /* fall through to get FS */ 2666 2667/*---------------------------------------------------------------------------- 2668 * get_fs_d -- 2669 * 2670 * Read (double precision) the FS register (bits 15-11) and 2671 * break up into fields. 2672 * This is an internal routine used by MipsEmulateFP only. 2673 * 2674 * Results: 2675 * t0 contains the sign 2676 * t1 contains the (biased) exponent 2677 * t2 contains the fraction 2678 * t3 contains the remaining fraction 2679 * 2680 *---------------------------------------------------------------------------- 2681 */ 2682ALEAF(get_fs_d) 2683 srl a3, a0, 12 - 2 # get FS field (even regs only) 2684 and a3, a3, 0xF << 2 # mask FS field 2685 lw a3, get_fs_d_tbl(a3) # switch on register number 2686 j a3 2687 2688 .rdata 2689get_fs_d_tbl: 2690 .word get_fs_d_f0 2691 .word get_fs_d_f2 2692 .word get_fs_d_f4 2693 .word get_fs_d_f6 2694 .word get_fs_d_f8 2695 .word get_fs_d_f10 2696 .word get_fs_d_f12 2697 .word get_fs_d_f14 2698 .word get_fs_d_f16 2699 .word get_fs_d_f18 2700 .word get_fs_d_f20 2701 .word get_fs_d_f22 2702 .word get_fs_d_f24 2703 .word get_fs_d_f26 2704 .word get_fs_d_f28 2705 .word get_fs_d_f30 2706 .text 2707 2708get_fs_d_f0: 2709 mfc1 t3, $f0 2710 mfc1 t0, $f1 2711 b get_fs_d_done 2712get_fs_d_f2: 2713 mfc1 t3, $f2 2714 mfc1 t0, $f3 2715 b get_fs_d_done 2716get_fs_d_f4: 2717 mfc1 t3, $f4 2718 mfc1 t0, $f5 2719 b get_fs_d_done 2720get_fs_d_f6: 2721 mfc1 t3, $f6 2722 mfc1 t0, $f7 2723 b get_fs_d_done 2724get_fs_d_f8: 2725 mfc1 t3, $f8 2726 mfc1 t0, $f9 2727 b get_fs_d_done 2728get_fs_d_f10: 2729 mfc1 t3, $f10 2730 mfc1 t0, $f11 2731 b get_fs_d_done 2732get_fs_d_f12: 2733 mfc1 t3, $f12 2734 mfc1 t0, $f13 2735 b get_fs_d_done 2736get_fs_d_f14: 2737 mfc1 t3, $f14 2738 mfc1 t0, $f15 2739 b get_fs_d_done 2740get_fs_d_f16: 2741 mfc1 t3, $f16 2742 mfc1 t0, $f17 2743 b get_fs_d_done 2744get_fs_d_f18: 2745 mfc1 t3, $f18 2746 mfc1 t0, $f19 2747 b get_fs_d_done 2748get_fs_d_f20: 2749 mfc1 t3, $f20 2750 mfc1 t0, $f21 2751 b get_fs_d_done 2752get_fs_d_f22: 2753 mfc1 t3, $f22 2754 mfc1 t0, $f23 2755 b get_fs_d_done 2756get_fs_d_f24: 2757 mfc1 t3, $f24 2758 mfc1 t0, $f25 2759 b get_fs_d_done 2760get_fs_d_f26: 2761 mfc1 t3, $f26 2762 mfc1 t0, $f27 2763 b get_fs_d_done 2764get_fs_d_f28: 2765 mfc1 t3, $f28 2766 mfc1 t0, $f29 2767 b get_fs_d_done 2768get_fs_d_f30: 2769 mfc1 t3, $f30 2770 mfc1 t0, $f31 2771get_fs_d_done: 2772 srl t1, t0, 20 # get exponent 2773 and t1, t1, 0x7FF 2774 and t2, t0, 0xFFFFF # get fraction 2775 srl t0, t0, 31 # get sign 2776 bne t1, DEXP_INF, 1f # is it a signaling NAN? 2777 and v0, t2, DSIGNAL_NAN 2778 bne v0, zero, invalid_d 27791: 2780 j ra 2781END(get_ft_fs_d) 2782 2783/*---------------------------------------------------------------------------- 2784 * get_cmp_s -- 2785 * 2786 * Read (single precision) the FS register (bits 15-11) and 2787 * the FT register (bits 20-16) and break up into fields. 2788 * This is an internal routine used by MipsEmulateFP only. 2789 * 2790 * Results: 2791 * t0 contains the sign 2792 * t1 contains the (biased) exponent 2793 * t2 contains the fraction 2794 * ta0 contains the sign 2795 * ta1 contains the (biased) exponent 2796 * ta2 contains the fraction 2797 * 2798 *---------------------------------------------------------------------------- 2799 */ 2800LEAF(get_cmp_s) 2801 srl a3, a0, 12 - 2 # get FS field (even regs only) 2802 and a3, a3, 0xF << 2 # mask FS field 2803 lw a3, cmp_fs_s_tbl(a3) # switch on register number 2804 j a3 2805 2806 .rdata 2807cmp_fs_s_tbl: 2808 .word cmp_fs_s_f0 2809 .word cmp_fs_s_f2 2810 .word cmp_fs_s_f4 2811 .word cmp_fs_s_f6 2812 .word cmp_fs_s_f8 2813 .word cmp_fs_s_f10 2814 .word cmp_fs_s_f12 2815 .word cmp_fs_s_f14 2816 .word cmp_fs_s_f16 2817 .word cmp_fs_s_f18 2818 .word cmp_fs_s_f20 2819 .word cmp_fs_s_f22 2820 .word cmp_fs_s_f24 2821 .word cmp_fs_s_f26 2822 .word cmp_fs_s_f28 2823 .word cmp_fs_s_f30 2824 .text 2825 2826cmp_fs_s_f0: 2827 mfc1 t0, $f0 2828 b cmp_fs_s_done 2829cmp_fs_s_f2: 2830 mfc1 t0, $f2 2831 b cmp_fs_s_done 2832cmp_fs_s_f4: 2833 mfc1 t0, $f4 2834 b cmp_fs_s_done 2835cmp_fs_s_f6: 2836 mfc1 t0, $f6 2837 b cmp_fs_s_done 2838cmp_fs_s_f8: 2839 mfc1 t0, $f8 2840 b cmp_fs_s_done 2841cmp_fs_s_f10: 2842 mfc1 t0, $f10 2843 b cmp_fs_s_done 2844cmp_fs_s_f12: 2845 mfc1 t0, $f12 2846 b cmp_fs_s_done 2847cmp_fs_s_f14: 2848 mfc1 t0, $f14 2849 b cmp_fs_s_done 2850cmp_fs_s_f16: 2851 mfc1 t0, $f16 2852 b cmp_fs_s_done 2853cmp_fs_s_f18: 2854 mfc1 t0, $f18 2855 b cmp_fs_s_done 2856cmp_fs_s_f20: 2857 mfc1 t0, $f20 2858 b cmp_fs_s_done 2859cmp_fs_s_f22: 2860 mfc1 t0, $f22 2861 b cmp_fs_s_done 2862cmp_fs_s_f24: 2863 mfc1 t0, $f24 2864 b cmp_fs_s_done 2865cmp_fs_s_f26: 2866 mfc1 t0, $f26 2867 b cmp_fs_s_done 2868cmp_fs_s_f28: 2869 mfc1 t0, $f28 2870 b cmp_fs_s_done 2871cmp_fs_s_f30: 2872 mfc1 t0, $f30 2873cmp_fs_s_done: 2874 srl t1, t0, 23 # get exponent 2875 and t1, t1, 0xFF 2876 and t2, t0, 0x7FFFFF # get fraction 2877 srl t0, t0, 31 # get sign 2878 2879 srl a3, a0, 17 - 2 # get FT field (even regs only) 2880 and a3, a3, 0xF << 2 # mask FT field 2881 lw a3, cmp_ft_s_tbl(a3) # switch on register number 2882 j a3 2883 2884 .rdata 2885cmp_ft_s_tbl: 2886 .word cmp_ft_s_f0 2887 .word cmp_ft_s_f2 2888 .word cmp_ft_s_f4 2889 .word cmp_ft_s_f6 2890 .word cmp_ft_s_f8 2891 .word cmp_ft_s_f10 2892 .word cmp_ft_s_f12 2893 .word cmp_ft_s_f14 2894 .word cmp_ft_s_f16 2895 .word cmp_ft_s_f18 2896 .word cmp_ft_s_f20 2897 .word cmp_ft_s_f22 2898 .word cmp_ft_s_f24 2899 .word cmp_ft_s_f26 2900 .word cmp_ft_s_f28 2901 .word cmp_ft_s_f30 2902 .text 2903 2904cmp_ft_s_f0: 2905 mfc1 ta0, $f0 2906 b cmp_ft_s_done 2907cmp_ft_s_f2: 2908 mfc1 ta0, $f2 2909 b cmp_ft_s_done 2910cmp_ft_s_f4: 2911 mfc1 ta0, $f4 2912 b cmp_ft_s_done 2913cmp_ft_s_f6: 2914 mfc1 ta0, $f6 2915 b cmp_ft_s_done 2916cmp_ft_s_f8: 2917 mfc1 ta0, $f8 2918 b cmp_ft_s_done 2919cmp_ft_s_f10: 2920 mfc1 ta0, $f10 2921 b cmp_ft_s_done 2922cmp_ft_s_f12: 2923 mfc1 ta0, $f12 2924 b cmp_ft_s_done 2925cmp_ft_s_f14: 2926 mfc1 ta0, $f14 2927 b cmp_ft_s_done 2928cmp_ft_s_f16: 2929 mfc1 ta0, $f16 2930 b cmp_ft_s_done 2931cmp_ft_s_f18: 2932 mfc1 ta0, $f18 2933 b cmp_ft_s_done 2934cmp_ft_s_f20: 2935 mfc1 ta0, $f20 2936 b cmp_ft_s_done 2937cmp_ft_s_f22: 2938 mfc1 ta0, $f22 2939 b cmp_ft_s_done 2940cmp_ft_s_f24: 2941 mfc1 ta0, $f24 2942 b cmp_ft_s_done 2943cmp_ft_s_f26: 2944 mfc1 ta0, $f26 2945 b cmp_ft_s_done 2946cmp_ft_s_f28: 2947 mfc1 ta0, $f28 2948 b cmp_ft_s_done 2949cmp_ft_s_f30: 2950 mfc1 ta0, $f30 2951cmp_ft_s_done: 2952 srl ta1, ta0, 23 # get exponent 2953 and ta1, ta1, 0xFF 2954 and ta2, ta0, 0x7FFFFF # get fraction 2955 srl ta0, ta0, 31 # get sign 2956 j ra 2957END(get_cmp_s) 2958 2959/*---------------------------------------------------------------------------- 2960 * get_cmp_d -- 2961 * 2962 * Read (double precision) the FS register (bits 15-11) and 2963 * the FT register (bits 20-16) and break up into fields. 2964 * This is an internal routine used by MipsEmulateFP only. 2965 * 2966 * Results: 2967 * t0 contains the sign 2968 * t1 contains the (biased) exponent 2969 * t2 contains the fraction 2970 * t3 contains the remaining fraction 2971 * ta0 contains the sign 2972 * ta1 contains the (biased) exponent 2973 * ta2 contains the fraction 2974 * ta3 contains the remaining fraction 2975 * 2976 *---------------------------------------------------------------------------- 2977 */ 2978LEAF(get_cmp_d) 2979 srl a3, a0, 12 - 2 # get FS field (even regs only) 2980 and a3, a3, 0xF << 2 # mask FS field 2981 lw a3, cmp_fs_d_tbl(a3) # switch on register number 2982 j a3 2983 2984 .rdata 2985cmp_fs_d_tbl: 2986 .word cmp_fs_d_f0 2987 .word cmp_fs_d_f2 2988 .word cmp_fs_d_f4 2989 .word cmp_fs_d_f6 2990 .word cmp_fs_d_f8 2991 .word cmp_fs_d_f10 2992 .word cmp_fs_d_f12 2993 .word cmp_fs_d_f14 2994 .word cmp_fs_d_f16 2995 .word cmp_fs_d_f18 2996 .word cmp_fs_d_f20 2997 .word cmp_fs_d_f22 2998 .word cmp_fs_d_f24 2999 .word cmp_fs_d_f26 3000 .word cmp_fs_d_f28 3001 .word cmp_fs_d_f30 3002 .text 3003 3004cmp_fs_d_f0: 3005 mfc1 t3, $f0 3006 mfc1 t0, $f1 3007 b cmp_fs_d_done 3008cmp_fs_d_f2: 3009 mfc1 t3, $f2 3010 mfc1 t0, $f3 3011 b cmp_fs_d_done 3012cmp_fs_d_f4: 3013 mfc1 t3, $f4 3014 mfc1 t0, $f5 3015 b cmp_fs_d_done 3016cmp_fs_d_f6: 3017 mfc1 t3, $f6 3018 mfc1 t0, $f7 3019 b cmp_fs_d_done 3020cmp_fs_d_f8: 3021 mfc1 t3, $f8 3022 mfc1 t0, $f9 3023 b cmp_fs_d_done 3024cmp_fs_d_f10: 3025 mfc1 t3, $f10 3026 mfc1 t0, $f11 3027 b cmp_fs_d_done 3028cmp_fs_d_f12: 3029 mfc1 t3, $f12 3030 mfc1 t0, $f13 3031 b cmp_fs_d_done 3032cmp_fs_d_f14: 3033 mfc1 t3, $f14 3034 mfc1 t0, $f15 3035 b cmp_fs_d_done 3036cmp_fs_d_f16: 3037 mfc1 t3, $f16 3038 mfc1 t0, $f17 3039 b cmp_fs_d_done 3040cmp_fs_d_f18: 3041 mfc1 t3, $f18 3042 mfc1 t0, $f19 3043 b cmp_fs_d_done 3044cmp_fs_d_f20: 3045 mfc1 t3, $f20 3046 mfc1 t0, $f21 3047 b cmp_fs_d_done 3048cmp_fs_d_f22: 3049 mfc1 t3, $f22 3050 mfc1 t0, $f23 3051 b cmp_fs_d_done 3052cmp_fs_d_f24: 3053 mfc1 t3, $f24 3054 mfc1 t0, $f25 3055 b cmp_fs_d_done 3056cmp_fs_d_f26: 3057 mfc1 t3, $f26 3058 mfc1 t0, $f27 3059 b cmp_fs_d_done 3060cmp_fs_d_f28: 3061 mfc1 t3, $f28 3062 mfc1 t0, $f29 3063 b cmp_fs_d_done 3064cmp_fs_d_f30: 3065 mfc1 t3, $f30 3066 mfc1 t0, $f31 3067cmp_fs_d_done: 3068 srl t1, t0, 20 # get exponent 3069 and t1, t1, 0x7FF 3070 and t2, t0, 0xFFFFF # get fraction 3071 srl t0, t0, 31 # get sign 3072 3073 srl a3, a0, 17 - 2 # get FT field (even regs only) 3074 and a3, a3, 0xF << 2 # mask FT field 3075 lw a3, cmp_ft_d_tbl(a3) # switch on register number 3076 j a3 3077 3078 .rdata 3079cmp_ft_d_tbl: 3080 .word cmp_ft_d_f0 3081 .word cmp_ft_d_f2 3082 .word cmp_ft_d_f4 3083 .word cmp_ft_d_f6 3084 .word cmp_ft_d_f8 3085 .word cmp_ft_d_f10 3086 .word cmp_ft_d_f12 3087 .word cmp_ft_d_f14 3088 .word cmp_ft_d_f16 3089 .word cmp_ft_d_f18 3090 .word cmp_ft_d_f20 3091 .word cmp_ft_d_f22 3092 .word cmp_ft_d_f24 3093 .word cmp_ft_d_f26 3094 .word cmp_ft_d_f28 3095 .word cmp_ft_d_f30 3096 .text 3097 3098cmp_ft_d_f0: 3099 mfc1 ta3, $f0 3100 mfc1 ta0, $f1 3101 b cmp_ft_d_done 3102cmp_ft_d_f2: 3103 mfc1 ta3, $f2 3104 mfc1 ta0, $f3 3105 b cmp_ft_d_done 3106cmp_ft_d_f4: 3107 mfc1 ta3, $f4 3108 mfc1 ta0, $f5 3109 b cmp_ft_d_done 3110cmp_ft_d_f6: 3111 mfc1 ta3, $f6 3112 mfc1 ta0, $f7 3113 b cmp_ft_d_done 3114cmp_ft_d_f8: 3115 mfc1 ta3, $f8 3116 mfc1 ta0, $f9 3117 b cmp_ft_d_done 3118cmp_ft_d_f10: 3119 mfc1 ta3, $f10 3120 mfc1 ta0, $f11 3121 b cmp_ft_d_done 3122cmp_ft_d_f12: 3123 mfc1 ta3, $f12 3124 mfc1 ta0, $f13 3125 b cmp_ft_d_done 3126cmp_ft_d_f14: 3127 mfc1 ta3, $f14 3128 mfc1 ta0, $f15 3129 b cmp_ft_d_done 3130cmp_ft_d_f16: 3131 mfc1 ta3, $f16 3132 mfc1 ta0, $f17 3133 b cmp_ft_d_done 3134cmp_ft_d_f18: 3135 mfc1 ta3, $f18 3136 mfc1 ta0, $f19 3137 b cmp_ft_d_done 3138cmp_ft_d_f20: 3139 mfc1 ta3, $f20 3140 mfc1 ta0, $f21 3141 b cmp_ft_d_done 3142cmp_ft_d_f22: 3143 mfc1 ta3, $f22 3144 mfc1 ta0, $f23 3145 b cmp_ft_d_done 3146cmp_ft_d_f24: 3147 mfc1 ta3, $f24 3148 mfc1 ta0, $f25 3149 b cmp_ft_d_done 3150cmp_ft_d_f26: 3151 mfc1 ta3, $f26 3152 mfc1 ta0, $f27 3153 b cmp_ft_d_done 3154cmp_ft_d_f28: 3155 mfc1 ta3, $f28 3156 mfc1 ta0, $f29 3157 b cmp_ft_d_done 3158cmp_ft_d_f30: 3159 mfc1 ta3, $f30 3160 mfc1 ta0, $f31 3161cmp_ft_d_done: 3162 srl ta1, ta0, 20 # get exponent 3163 and ta1, ta1, 0x7FF 3164 and ta2, ta0, 0xFFFFF # get fraction 3165 srl ta0, ta0, 31 # get sign 3166 j ra 3167END(get_cmp_d) 3168 3169/*---------------------------------------------------------------------------- 3170 * set_fd_s -- 3171 * 3172 * Write (single precision) the FD register (bits 10-6). 3173 * This is an internal routine used by MipsEmulateFP only. 3174 * 3175 * Arguments: 3176 * a0 contains the FP instruction 3177 * t0 contains the sign 3178 * t1 contains the (biased) exponent 3179 * t2 contains the fraction 3180 * 3181 * set_fd_word -- 3182 * 3183 * Write (integer) the FD register (bits 10-6). 3184 * This is an internal routine used by MipsEmulateFP only. 3185 * 3186 * Arguments: 3187 * a0 contains the FP instruction 3188 * t2 contains the integer 3189 * 3190 *---------------------------------------------------------------------------- 3191 */ 3192LEAF(set_fd_s) 3193 sll t0, t0, 31 # position sign 3194 sll t1, t1, 23 # position exponent 3195 or t2, t2, t0 3196 or t2, t2, t1 3197ALEAF(set_fd_word) 3198 srl a3, a0, 7 - 2 # get FD field (even regs only) 3199 and a3, a3, 0xF << 2 # mask FT field 3200 lw a3, set_fd_s_tbl(a3) # switch on register number 3201 j a3 3202 3203 .rdata 3204set_fd_s_tbl: 3205 .word set_fd_s_f0 3206 .word set_fd_s_f2 3207 .word set_fd_s_f4 3208 .word set_fd_s_f6 3209 .word set_fd_s_f8 3210 .word set_fd_s_f10 3211 .word set_fd_s_f12 3212 .word set_fd_s_f14 3213 .word set_fd_s_f16 3214 .word set_fd_s_f18 3215 .word set_fd_s_f20 3216 .word set_fd_s_f22 3217 .word set_fd_s_f24 3218 .word set_fd_s_f26 3219 .word set_fd_s_f28 3220 .word set_fd_s_f30 3221 .text 3222 3223set_fd_s_f0: 3224 mtc1 t2, $f0 3225 j ra 3226set_fd_s_f2: 3227 mtc1 t2, $f2 3228 j ra 3229set_fd_s_f4: 3230 mtc1 t2, $f4 3231 j ra 3232set_fd_s_f6: 3233 mtc1 t2, $f6 3234 j ra 3235set_fd_s_f8: 3236 mtc1 t2, $f8 3237 j ra 3238set_fd_s_f10: 3239 mtc1 t2, $f10 3240 j ra 3241set_fd_s_f12: 3242 mtc1 t2, $f12 3243 j ra 3244set_fd_s_f14: 3245 mtc1 t2, $f14 3246 j ra 3247set_fd_s_f16: 3248 mtc1 t2, $f16 3249 j ra 3250set_fd_s_f18: 3251 mtc1 t2, $f18 3252 j ra 3253set_fd_s_f20: 3254 mtc1 t2, $f20 3255 j ra 3256set_fd_s_f22: 3257 mtc1 t2, $f22 3258 j ra 3259set_fd_s_f24: 3260 mtc1 t2, $f24 3261 j ra 3262set_fd_s_f26: 3263 mtc1 t2, $f26 3264 j ra 3265set_fd_s_f28: 3266 mtc1 t2, $f28 3267 j ra 3268set_fd_s_f30: 3269 mtc1 t2, $f30 3270 j ra 3271END(set_fd_s) 3272 3273/*---------------------------------------------------------------------------- 3274 * set_fd_d -- 3275 * 3276 * Write (double precision) the FT register (bits 10-6). 3277 * This is an internal routine used by MipsEmulateFP only. 3278 * 3279 * Arguments: 3280 * a0 contains the FP instruction 3281 * t0 contains the sign 3282 * t1 contains the (biased) exponent 3283 * t2 contains the fraction 3284 * t3 contains the remaining fraction 3285 * 3286 *---------------------------------------------------------------------------- 3287 */ 3288LEAF(set_fd_d) 3289 sll t0, t0, 31 # set sign 3290 sll t1, t1, 20 # set exponent 3291 or t0, t0, t1 3292 or t0, t0, t2 # set fraction 3293 srl a3, a0, 7 - 2 # get FD field (even regs only) 3294 and a3, a3, 0xF << 2 # mask FD field 3295 lw a3, set_fd_d_tbl(a3) # switch on register number 3296 j a3 3297 3298 .rdata 3299set_fd_d_tbl: 3300 .word set_fd_d_f0 3301 .word set_fd_d_f2 3302 .word set_fd_d_f4 3303 .word set_fd_d_f6 3304 .word set_fd_d_f8 3305 .word set_fd_d_f10 3306 .word set_fd_d_f12 3307 .word set_fd_d_f14 3308 .word set_fd_d_f16 3309 .word set_fd_d_f18 3310 .word set_fd_d_f20 3311 .word set_fd_d_f22 3312 .word set_fd_d_f24 3313 .word set_fd_d_f26 3314 .word set_fd_d_f28 3315 .word set_fd_d_f30 3316 .text 3317 3318set_fd_d_f0: 3319 mtc1 t3, $f0 3320 mtc1 t0, $f1 3321 j ra 3322set_fd_d_f2: 3323 mtc1 t3, $f2 3324 mtc1 t0, $f3 3325 j ra 3326set_fd_d_f4: 3327 mtc1 t3, $f4 3328 mtc1 t0, $f5 3329 j ra 3330set_fd_d_f6: 3331 mtc1 t3, $f6 3332 mtc1 t0, $f7 3333 j ra 3334set_fd_d_f8: 3335 mtc1 t3, $f8 3336 mtc1 t0, $f9 3337 j ra 3338set_fd_d_f10: 3339 mtc1 t3, $f10 3340 mtc1 t0, $f11 3341 j ra 3342set_fd_d_f12: 3343 mtc1 t3, $f12 3344 mtc1 t0, $f13 3345 j ra 3346set_fd_d_f14: 3347 mtc1 t3, $f14 3348 mtc1 t0, $f15 3349 j ra 3350set_fd_d_f16: 3351 mtc1 t3, $f16 3352 mtc1 t0, $f17 3353 j ra 3354set_fd_d_f18: 3355 mtc1 t3, $f18 3356 mtc1 t0, $f19 3357 j ra 3358set_fd_d_f20: 3359 mtc1 t3, $f20 3360 mtc1 t0, $f21 3361 j ra 3362set_fd_d_f22: 3363 mtc1 t3, $f22 3364 mtc1 t0, $f23 3365 j ra 3366set_fd_d_f24: 3367 mtc1 t3, $f24 3368 mtc1 t0, $f25 3369 j ra 3370set_fd_d_f26: 3371 mtc1 t3, $f26 3372 mtc1 t0, $f27 3373 j ra 3374set_fd_d_f28: 3375 mtc1 t3, $f28 3376 mtc1 t0, $f29 3377 j ra 3378set_fd_d_f30: 3379 mtc1 t3, $f30 3380 mtc1 t0, $f31 3381 j ra 3382END(set_fd_d) 3383 3384/*---------------------------------------------------------------------------- 3385 * renorm_fs_s -- 3386 * 3387 * Results: 3388 * t1 unbiased exponent 3389 * t2 normalized fraction 3390 * 3391 *---------------------------------------------------------------------------- 3392 */ 3393LEAF(renorm_fs_s) 3394/* 3395 * Find out how many leading zero bits are in t2 and put in t9. 3396 */ 3397 move v0, t2 3398 move t9, zero 3399 srl v1, v0, 16 3400 bne v1, zero, 1f 3401 addu t9, 16 3402 sll v0, 16 34031: 3404 srl v1, v0, 24 3405 bne v1, zero, 1f 3406 addu t9, 8 3407 sll v0, 8 34081: 3409 srl v1, v0, 28 3410 bne v1, zero, 1f 3411 addu t9, 4 3412 sll v0, 4 34131: 3414 srl v1, v0, 30 3415 bne v1, zero, 1f 3416 addu t9, 2 3417 sll v0, 2 34181: 3419 srl v1, v0, 31 3420 bne v1, zero, 1f 3421 addu t9, 1 3422/* 3423 * Now shift t2 the correct number of bits. 3424 */ 34251: 3426 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros 3427 li t1, SEXP_MIN 3428 subu t1, t1, t9 # adjust exponent 3429 sll t2, t2, t9 3430 j ra 3431END(renorm_fs_s) 3432 3433/*---------------------------------------------------------------------------- 3434 * renorm_fs_d -- 3435 * 3436 * Results: 3437 * t1 unbiased exponent 3438 * t2,t3 normalized fraction 3439 * 3440 *---------------------------------------------------------------------------- 3441 */ 3442LEAF(renorm_fs_d) 3443/* 3444 * Find out how many leading zero bits are in t2,t3 and put in t9. 3445 */ 3446 move v0, t2 3447 move t9, zero 3448 bne t2, zero, 1f 3449 move v0, t3 3450 addu t9, 32 34511: 3452 srl v1, v0, 16 3453 bne v1, zero, 1f 3454 addu t9, 16 3455 sll v0, 16 34561: 3457 srl v1, v0, 24 3458 bne v1, zero, 1f 3459 addu t9, 8 3460 sll v0, 8 34611: 3462 srl v1, v0, 28 3463 bne v1, zero, 1f 3464 addu t9, 4 3465 sll v0, 4 34661: 3467 srl v1, v0, 30 3468 bne v1, zero, 1f 3469 addu t9, 2 3470 sll v0, 2 34711: 3472 srl v1, v0, 31 3473 bne v1, zero, 1f 3474 addu t9, 1 3475/* 3476 * Now shift t2,t3 the correct number of bits. 3477 */ 34781: 3479 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros 3480 li t1, DEXP_MIN 3481 subu t1, t1, t9 # adjust exponent 3482 li v0, 32 3483 blt t9, v0, 1f 3484 subu t9, t9, v0 # shift fraction left >= 32 bits 3485 sll t2, t3, t9 3486 move t3, zero 3487 j ra 34881: 3489 subu v0, v0, t9 # shift fraction left < 32 bits 3490 sll t2, t2, t9 3491 srl v1, t3, v0 3492 or t2, t2, v1 3493 sll t3, t3, t9 3494 j ra 3495END(renorm_fs_d) 3496 3497/*---------------------------------------------------------------------------- 3498 * renorm_ft_s -- 3499 * 3500 * Results: 3501 * ta1 unbiased exponent 3502 * ta2 normalized fraction 3503 * 3504 *---------------------------------------------------------------------------- 3505 */ 3506LEAF(renorm_ft_s) 3507/* 3508 * Find out how many leading zero bits are in ta2 and put in t9. 3509 */ 3510 move v0, ta2 3511 move t9, zero 3512 srl v1, v0, 16 3513 bne v1, zero, 1f 3514 addu t9, 16 3515 sll v0, 16 35161: 3517 srl v1, v0, 24 3518 bne v1, zero, 1f 3519 addu t9, 8 3520 sll v0, 8 35211: 3522 srl v1, v0, 28 3523 bne v1, zero, 1f 3524 addu t9, 4 3525 sll v0, 4 35261: 3527 srl v1, v0, 30 3528 bne v1, zero, 1f 3529 addu t9, 2 3530 sll v0, 2 35311: 3532 srl v1, v0, 31 3533 bne v1, zero, 1f 3534 addu t9, 1 3535/* 3536 * Now shift ta2 the correct number of bits. 3537 */ 35381: 3539 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros 3540 li ta1, SEXP_MIN 3541 subu ta1, ta1, t9 # adjust exponent 3542 sll ta2, ta2, t9 3543 j ra 3544END(renorm_ft_s) 3545 3546/*---------------------------------------------------------------------------- 3547 * renorm_ft_d -- 3548 * 3549 * Results: 3550 * ta1 unbiased exponent 3551 * ta2,ta3 normalized fraction 3552 * 3553 *---------------------------------------------------------------------------- 3554 */ 3555LEAF(renorm_ft_d) 3556/* 3557 * Find out how many leading zero bits are in ta2,ta3 and put in t9. 3558 */ 3559 move v0, ta2 3560 move t9, zero 3561 bne ta2, zero, 1f 3562 move v0, ta3 3563 addu t9, 32 35641: 3565 srl v1, v0, 16 3566 bne v1, zero, 1f 3567 addu t9, 16 3568 sll v0, 16 35691: 3570 srl v1, v0, 24 3571 bne v1, zero, 1f 3572 addu t9, 8 3573 sll v0, 8 35741: 3575 srl v1, v0, 28 3576 bne v1, zero, 1f 3577 addu t9, 4 3578 sll v0, 4 35791: 3580 srl v1, v0, 30 3581 bne v1, zero, 1f 3582 addu t9, 2 3583 sll v0, 2 35841: 3585 srl v1, v0, 31 3586 bne v1, zero, 1f 3587 addu t9, 1 3588/* 3589 * Now shift ta2,ta3 the correct number of bits. 3590 */ 35911: 3592 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros 3593 li ta1, DEXP_MIN 3594 subu ta1, ta1, t9 # adjust exponent 3595 li v0, 32 3596 blt t9, v0, 1f 3597 subu t9, t9, v0 # shift fraction left >= 32 bits 3598 sll ta2, ta3, t9 3599 move ta3, zero 3600 j ra 36011: 3602 subu v0, v0, t9 # shift fraction left < 32 bits 3603 sll ta2, ta2, t9 3604 srl v1, ta3, v0 3605 or ta2, ta2, v1 3606 sll ta3, ta3, t9 3607 j ra 3608END(renorm_ft_d) 3609