1/* $NetBSD: fp.S,v 1.23 2002/11/04 18:54:13 thorpej Exp $ */ 2 3/* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Ralph Campbell. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)fp.s 8.1 (Berkeley) 6/10/93 39 */ 40 41#include <sys/cdefs.h> 42 43#include <mips/asm.h> 44#include <mips/cpuregs.h> 45#include <mips/trap.h> 46 47#include "assym.h" 48 49#define SEXP_INF 0xff 50#define DEXP_INF 0x7ff 51#define SEXP_BIAS 127 52#define DEXP_BIAS 1023 53#define SEXP_MIN -126 54#define DEXP_MIN -1022 55#define SEXP_MAX 127 56#define DEXP_MAX 1023 57#define WEXP_MAX 30 /* maximum unbiased exponent for int */ 58#define WEXP_MIN -1 /* minimum unbiased exponent for int */ 59#define SFRAC_BITS 23 60#define DFRAC_BITS 52 61#define SIMPL_ONE 0x00800000 62#define DIMPL_ONE 0x00100000 63#define SLEAD_ZEROS 31 - 23 64#define DLEAD_ZEROS 31 - 20 65#define STICKYBIT 1 66#define GUARDBIT 0x80000000 67#define SSIGNAL_NAN 0x00400000 68#define DSIGNAL_NAN 0x00080000 69#define SQUIET_NAN 0x003fffff 70#define DQUIET_NAN0 0x0007ffff 71#define DQUIET_NAN1 0xffffffff 72#define INT_MIN 0x80000000 73#define INT_MAX 0x7fffffff 74 75#define COND_UNORDERED 0x1 76#define COND_EQUAL 0x2 77#define COND_LESS 0x4 78#define COND_SIGNAL 0x8 79 80#if SZREG == 8 81#define SZREG_SHFT 3 82#define SZREG_MASK 0x00f8 83#else 84#define SZREG_SHFT 2 85#define SZREG_MASK 0x007c 86#endif 87 88/* insns are reordered in the way as MIPS architecture imposes */ 89 .set reorder 90 91/*---------------------------------------------------------------------------- 92 * 93 * MachEmulateFP -- 94 * 95 * Emulate unimplemented floating point operations. 96 * This routine should only be called by MachFPInterrupt(). 97 * 98 * MachEmulateFP(instr, frame, cause) 99 * u_int32_t instr; 100 * struct frame *frame; 101 * u_int32_t cause; 102 * 103 * Results: 104 * None. 105 * 106 * Side effects: 107 * Floating point registers are modified according to instruction. 108 * 109 *---------------------------------------------------------------------------- 110 */ 111NESTED(MachEmulateFP, CALLFRAME_SIZ, ra) 112 subu sp, sp, CALLFRAME_SIZ 113 sw ra, CALLFRAME_RA(sp) 114 sw a1, CALLFRAME_SIZ + 16(sp) 115 sw a2, CALLFRAME_SIZ + 8(sp) 116/* 117 * Decode the FMT field (bits 25-21) and FUNCTION field (bits 5-0). 118 */ 119 srl v0, a0, 21 - 2 # get FMT field 120 andi v0, v0, 0x1F << 2 # mask FMT field 121#ifdef SOFTFLOAT 122 lw t0, _C_LABEL(curpcb) # get pcb of current process 123 lw a3, fmt_tbl(v0) # switch on FUNC & FMT 124 lw a2, U_PCB_FPREGS+FRAME_FSR(t0) 125#else 126 cfc1 a2, MIPS_FPU_CSR # get exception register 127 lw a3, fmt_tbl(v0) # switch on FUNC & FMT 128 and a2, a2, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception 129 ctc1 a2, MIPS_FPU_CSR 130#endif 131 j a3 132 133single_op: 134 andi v0, a0, 0x3F # get FUNC field 135 sll v0, v0, 2 136 lw v0, func_single_tbl(v0) 137 j v0 138double_op: 139 andi v0, a0, 0x3F # get FUNC field 140 sll v0, v0, 2 141 lw v0, func_double_tbl(v0) 142 j v0 143single_fixed_op: 144 andi v0, a0, 0x3F # get FUNC field 145 sll v0, v0, 2 146 lw v0, func_single_fixed_tbl(v0) 147 j v0 148long_fixed_op: 149 andi v0, a0, 0x3F # get FUNC field 150 sll v0, v0, 2 151 lw v0, func_long_fixed_tbl(v0) 152 j v0 153 154 .rdata 155fmt_tbl: 156#ifdef SOFTFLOAT 157 .word mfromc1 # sub 0 158#else 159 .word ill # sub 0 160#endif 161 .word ill # sub 1 162#ifdef SOFTFLOAT 163 .word cfromc1 # sub 2 164#else 165 .word ill # sub 2 166#endif 167 .word ill # sub 3 168#ifdef SOFTFLOAT 169 .word mtoc1 # sub 4 170#else 171 .word ill # sub 4 172#endif 173 .word ill # sub 5 174#ifdef SOFTFLOAT 175 .word ctoc1 # sub 6 176#else 177 .word ill # sub 6 178#endif 179 .word ill # sub 7 180#ifdef SOFTFLOAT 181 .word branchc1 # sub 8 182#else 183 .word ill # sub 8 184#endif 185 .word ill # sub 9 186 .word ill # sub 10 187 .word ill # sub 11 188 .word ill # sub 12 189 .word ill # sub 13 190 .word ill # sub 14 191 .word ill # sub 15 192 .word single_op # sub 16 193 .word double_op # sub 17 194 .word ill # sub 18 195 .word ill # sub 19 196 .word single_fixed_op # sub 20 197 .word long_fixed_op # sub 21 198 .word ill # sub 22 199 .word ill # sub 23 200 .word ill # sub 24 201 .word ill # sub 25 202 .word ill # sub 26 203 .word ill # sub 27 204 .word ill # sub 28 205 .word ill # sub 29 206 .word ill # sub 30 207 .word ill # sub 31 208 209func_single_tbl: 210 .word add_s # func 0 211 .word sub_s # func 1 212 .word mul_s # func 2 213 .word div_s # func 3 214#ifdef MIPS3_PLUS 215 .word sqrt_s # func 4 216#else 217 .word ill # func 4 218#endif 219 .word abs_s # func 5 220 .word mov_s # func 6 221 .word neg_s # func 7 222 .word ill # func 8 223 .word ill # func 9 224 .word ill # func 10 225 .word ill # func 11 226#ifdef MIPS3_PLUS 227 .word round_w_s # func 12 /* MIPS2 FP instructions */ 228 .word trunc_w_s # func 13 229 .word ceil_w_s # func 14 230 .word floor_w_s # func 15 231#else 232 .word ill # func 12 233 .word ill # func 13 234 .word ill # func 14 235 .word ill # func 15 236#endif 237 .word ill # func 16 238 .word ill # func 17 239 .word ill # func 18 240 .word ill # func 19 241 .word ill # func 20 242 .word ill # func 21 243 .word ill # func 22 244 .word ill # func 23 245 .word ill # func 24 246 .word ill # func 25 247 .word ill # func 26 248 .word ill # func 27 249 .word ill # func 28 250 .word ill # func 29 251 .word ill # func 30 252 .word ill # func 31 253 .word ill # func 32 254 .word cvt_d_s # func 33 255 .word ill # func 34 256 .word ill # func 35 257 .word cvt_w_s # func 36 258 .word ill # func 37 259 .word ill # func 38 260 .word ill # func 39 261 .word ill # func 40 262 .word ill # func 41 263 .word ill # func 42 264 .word ill # func 43 265 .word ill # func 44 266 .word ill # func 45 267 .word ill # func 46 268 .word ill # func 47 269 .word cmp_s # func 48 270 .word cmp_s # func 49 271 .word cmp_s # func 50 272 .word cmp_s # func 51 273 .word cmp_s # func 52 274 .word cmp_s # func 53 275 .word cmp_s # func 54 276 .word cmp_s # func 55 277 .word cmp_s # func 56 278 .word cmp_s # func 57 279 .word cmp_s # func 58 280 .word cmp_s # func 59 281 .word cmp_s # func 60 282 .word cmp_s # func 61 283 .word cmp_s # func 62 284 .word cmp_s # func 63 285 286func_double_tbl: 287 .word add_d # func 0 288 .word sub_d # func 1 289 .word mul_d # func 2 290 .word div_d # func 3 291#ifdef MIPS3_PLUS 292 .word sqrt_d # func 4 293#else 294 .word ill # func 4 295#endif 296 .word abs_d # func 5 297 .word mov_d # func 6 298 .word neg_d # func 7 299 .word ill # func 8 300 .word ill # func 9 301 .word ill # func 10 302 .word ill # func 11 303#ifdef MIPS3_PLUS 304 .word round_w_d # func 12 /* MIPS2 FP instructions */ 305 .word trunc_w_d # func 13 306 .word ceil_w_d # func 14 307 .word floor_w_d # func 15 308#else 309 .word ill # func 12 310 .word ill # func 13 311 .word ill # func 14 312 .word ill # func 15 313#endif 314 .word ill # func 16 315 .word ill # func 17 316 .word ill # func 18 317 .word ill # func 19 318 .word ill # func 20 319 .word ill # func 21 320 .word ill # func 22 321 .word ill # func 23 322 .word ill # func 24 323 .word ill # func 25 324 .word ill # func 26 325 .word ill # func 27 326 .word ill # func 28 327 .word ill # func 29 328 .word ill # func 30 329 .word ill # func 31 330 .word cvt_s_d # func 32 331 .word ill # func 33 332 .word ill # func 34 333 .word ill # func 35 334 .word cvt_w_d # func 36 335 .word ill # func 37 336 .word ill # func 38 337 .word ill # func 39 338 .word ill # func 40 339 .word ill # func 41 340 .word ill # func 42 341 .word ill # func 43 342 .word ill # func 44 343 .word ill # func 45 344 .word ill # func 46 345 .word ill # func 47 346 .word cmp_d # func 48 347 .word cmp_d # func 49 348 .word cmp_d # func 50 349 .word cmp_d # func 51 350 .word cmp_d # func 52 351 .word cmp_d # func 53 352 .word cmp_d # func 54 353 .word cmp_d # func 55 354 .word cmp_d # func 56 355 .word cmp_d # func 57 356 .word cmp_d # func 58 357 .word cmp_d # func 59 358 .word cmp_d # func 60 359 .word cmp_d # func 61 360 .word cmp_d # func 62 361 .word cmp_d # func 63 362 363func_single_fixed_tbl: 364 .word ill # func 0 365 .word ill # func 1 366 .word ill # func 2 367 .word ill # func 3 368 .word ill # func 4 369 .word ill # func 5 370 .word ill # func 6 371 .word ill # func 7 372 .word ill # func 8 373 .word ill # func 9 374 .word ill # func 10 375 .word ill # func 11 376 .word ill # func 12 377 .word ill # func 13 378 .word ill # func 14 379 .word ill # func 15 380 .word ill # func 16 381 .word ill # func 17 382 .word ill # func 18 383 .word ill # func 19 384 .word ill # func 20 385 .word ill # func 21 386 .word ill # func 22 387 .word ill # func 23 388 .word ill # func 24 389 .word ill # func 25 390 .word ill # func 26 391 .word ill # func 27 392 .word ill # func 28 393 .word ill # func 29 394 .word ill # func 30 395 .word ill # func 31 396 .word cvt_s_w # func 32 397 .word cvt_d_w # func 33 398 .word ill # func 34 399 .word ill # func 35 400 .word ill # func 36 401 .word ill # func 37 402 .word ill # func 38 403 .word ill # func 39 404 .word ill # func 40 405 .word ill # func 41 406 .word ill # func 42 407 .word ill # func 43 408 .word ill # func 44 409 .word ill # func 45 410 .word ill # func 46 411 .word ill # func 47 412 .word ill # func 48 413 .word ill # func 49 414 .word ill # func 50 415 .word ill # func 51 416 .word ill # func 52 417 .word ill # func 53 418 .word ill # func 54 419 .word ill # func 55 420 .word ill # func 56 421 .word ill # func 57 422 .word ill # func 58 423 .word ill # func 59 424 .word ill # func 60 425 .word ill # func 61 426 .word ill # func 62 427 .word ill # func 63 428 429func_long_fixed_tbl: 430 .word ill # func 0 431 .word ill # func 1 432 .word ill # func 2 433 .word ill # func 3 434 .word ill # func 4 435 .word ill # func 5 436 .word ill # func 6 437 .word ill # func 7 438 .word ill # func 8 439 .word ill # func 9 440 .word ill # func 10 441 .word ill # func 11 442 .word ill # func 12 443 .word ill # func 13 444 .word ill # func 14 445 .word ill # func 15 446 .word ill # func 16 447 .word ill # func 17 448 .word ill # func 18 449 .word ill # func 19 450 .word ill # func 20 451 .word ill # func 21 452 .word ill # func 22 453 .word ill # func 23 454 .word ill # func 24 455 .word ill # func 25 456 .word ill # func 26 457 .word ill # func 27 458 .word ill # func 28 459 .word ill # func 29 460 .word ill # func 30 461 .word ill # func 31 462 .word ill # func 32 463 .word ill # func 33 464 .word ill # func 34 465 .word ill # func 35 466 .word ill # func 36 467 .word ill # func 37 468 .word ill # func 38 469 .word ill # func 39 470 .word ill # func 40 471 .word ill # func 41 472 .word ill # func 42 473 .word ill # func 43 474 .word ill # func 44 475 .word ill # func 45 476 .word ill # func 46 477 .word ill # func 47 478 .word ill # func 48 479 .word ill # func 49 480 .word ill # func 50 481 .word ill # func 51 482 .word ill # func 52 483 .word ill # func 53 484 .word ill # func 54 485 .word ill # func 55 486 .word ill # func 56 487 .word ill # func 57 488 .word ill # func 58 489 .word ill # func 59 490 .word ill # func 60 491 .word ill # func 61 492 .word ill # func 62 493 .word ill # func 63 494 495 .text 496 497#ifdef SOFTFLOAT 498mfromc1: 499 srl t1, a0, 11-2 500 lw t0, _C_LABEL(curpcb) # get pcb of current process 501 andi t1, t1, 0x007C 502 addu t0, t0, t1 503 504 lw v0, U_PCB_FPREGS+FRAME_FP0(t0) 505 506 srl t0, a0, 16-SZREG_SHFT 507 andi t0, t0, SZREG_MASK 508 addu t0, t0, a1 509 510 REG_PROLOGUE 511 REG_S v0, FRAME_ZERO(t0) 512 REG_EPILOGUE 513 514 b done 515 516mtoc1: 517 REG_PROLOGUE 518 REG_S zero, FRAME_ZERO(a1) # ensure zero has value 0 519 srl t0, a0, 16-SZREG_SHFT 520 andi t0, t0, SZREG_MASK 521 addu v0, a1, t0 522 REG_L v0, FRAME_ZERO(v0) 523 REG_EPILOGUE 524 525 srl t1, a0, 11-2 526 lw t0, _C_LABEL(curpcb) # get pcb of current process 527 andi t1, t1, 0x007C 528 addu t0, t0, t1 529 530 sw v0, U_PCB_FPREGS+FRAME_FP0(t0) 531 532 b done 533 534cfromc1: 535 srl t1, a0, 11 536 lw t0, _C_LABEL(curpcb) # get pcb of current process 537 andi t1, t1, 0x001F 538 li t2, 0x1F 539 move v0, zero 540 bne t1, t2, cfinvalid 541 542 lw v0, U_PCB_FPREGS+FRAME_FSR(t0) 543 544cfinvalid: 545 546 srl t0, a0, 16-SZREG_SHFT 547 andi t0, t0, SZREG_MASK 548 addu t0, t0, a1 549 550 REG_PROLOGUE 551 REG_S v0, FRAME_ZERO(t0) 552 REG_EPILOGUE 553 554 b done 555 556ctoc1: 557 REG_PROLOGUE 558 REG_S zero, FRAME_ZERO(a1) # ensure zero has value 0 559 REG_EPILOGUE 560 561 srl t0, a0, 11 562 andi t0, t0, 0x001F 563 li t1, 0x1F 564 bne t0, t1, done 565 566 srl t0, a0, 16-SZREG_SHFT 567 andi t0, t0, SZREG_MASK 568 addu v0, a1, t0 569 REG_PROLOGUE 570 REG_L v0, FRAME_ZERO(v0) 571 REG_EPILOGUE 572 lw t0, _C_LABEL(curpcb) # get pcb of current process 573 #nop 574 sw v0, U_PCB_FPREGS+FRAME_FSR(t0) 575 576 b done 577 578branchc1: 579 srl v0, a0, 16-2 580 andi v0, v0, 0x007C 581 lw v0, branchc1_tbl(v0) 582 j v0 583 584 .rdata 585branchc1_tbl: 586 .word bcfalse # br 0 587 .word bctrue # br 1 588 .word bcfalse_l # br 2 589 .word bctrue_l # br 3 590 .word ill # br 4 591 .word ill # br 5 592 .word ill # br 6 593 .word ill # br 7 594 .word ill # br 8 595 .word ill # br 9 596 .word ill # br 10 597 .word ill # br 11 598 .word ill # br 12 599 .word ill # br 13 600 .word ill # br 14 601 .word ill # br 15 602 .word ill # br 16 603 .word ill # br 17 604 .word ill # br 18 605 .word ill # br 19 606 .word ill # br 20 607 .word ill # br 21 608 .word ill # br 22 609 .word ill # br 23 610 .word ill # br 24 611 .word ill # br 25 612 .word ill # br 26 613 .word ill # br 27 614 .word ill # br 28 615 .word ill # br 29 616 .word ill # br 30 617 .word ill # br 31 618 619 .text 620 621bcfalse: 622 li v0, MIPS_FPU_COND_BIT 623 and v0, v0, a2 624 beq v0, zero, bcemul_branch 625 b done 626bctrue: 627 li v0, MIPS_FPU_COND_BIT 628 and v0, v0, a2 629 bne v0, zero, bcemul_branch 630 b done 631bcfalse_l: 632 li v0, MIPS_FPU_COND_BIT 633 and v0, v0, a2 634 beq v0, zero, bcemul_branch 635 REG_PROLOGUE 636 REG_L v0, FRAME_EPC(a1) 637 addiu v0, v0, 4 638 REG_S v0, FRAME_EPC(a1) 639 REG_EPILOGUE 640 b done 641bctrue_l: 642 li v0, MIPS_FPU_COND_BIT 643 and v0, v0, a2 644 bne v0, zero, bcemul_branch 645 REG_PROLOGUE 646 REG_L v0, FRAME_EPC(a1) 647 addiu v0, v0, 4 648 REG_S v0, FRAME_EPC(a1) 649 REG_EPILOGUE 650 b done 651 652bcemul_branch: 653 /* Fetch delay slot instruction */ 654 sw a1, CALLFRAME_SIZ + 4(sp) 655 REG_PROLOGUE 656 REG_L a0, FRAME_EPC(a1) 657 REG_EPILOGUE 658 addiu a0, a0, 4 659 jal _C_LABEL(fuiword) 660 661 move a0, v0 662 lw a1, CALLFRAME_SIZ + 4(sp) 663 lw a2, CALLFRAME_SIZ + 8(sp) 664 665 /* Update cause */ 666 li t0, MIPS_CR_BR_DELAY 667 or a2, a2, t0 668 669 /* Free MachEmulateFP call frame */ 670 lw ra, CALLFRAME_RA(sp) 671 addu sp, sp, CALLFRAME_SIZ 672 673 j _C_LABEL(bcemul_delay_slot) 674#endif 675 676/* 677 * Single precision subtract. 678 */ 679sub_s: 680 jal _C_LABEL(get_ft_fs_s) 681 xor ta0, ta0, 1 # negate FT sign bit 682 b add_sub_s 683/* 684 * Single precision add. 685 */ 686add_s: 687 jal _C_LABEL(get_ft_fs_s) 688add_sub_s: 689 bne t1, SEXP_INF, 1f # is FS an infinity? 690 bne ta1, SEXP_INF, result_fs_s # if FT is not inf, result=FS 691 bne t2, zero, result_fs_s # if FS is NAN, result is FS 692 bne ta2, zero, result_ft_s # if FT is NAN, result is FT 693 bne t0, ta0, invalid_s # both infinities same sign? 694 b result_fs_s # result is in FS 6951: 696 beq ta1, SEXP_INF, result_ft_s # if FT is inf, result=FT 697 bne t1, zero, 4f # is FS a denormalized num? 698 beq t2, zero, 3f # is FS zero? 699 bne ta1, zero, 2f # is FT a denormalized num? 700 beq ta2, zero, result_fs_s # FT is zero, result=FS 701 jal _C_LABEL(renorm_fs_s) 702 jal _C_LABEL(renorm_ft_s) 703 b 5f 7042: 705 jal _C_LABEL(renorm_fs_s) 706 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 707 or ta2, ta2, SIMPL_ONE # set implied one bit 708 b 5f 7093: 710 bne ta1, zero, result_ft_s # if FT != 0, result=FT 711 bne ta2, zero, result_ft_s 712 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 713 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 714 or t0, t0, ta0 # compute result sign 715 b result_fs_s 7161: 717 and t0, t0, ta0 # compute result sign 718 b result_fs_s 7194: 720 bne ta1, zero, 2f # is FT a denormalized num? 721 beq ta2, zero, result_fs_s # FT is zero, result=FS 722 subu t1, t1, SEXP_BIAS # unbias FS exponent 723 or t2, t2, SIMPL_ONE # set implied one bit 724 jal _C_LABEL(renorm_ft_s) 725 b 5f 7262: 727 subu t1, t1, SEXP_BIAS # unbias FS exponent 728 or t2, t2, SIMPL_ONE # set implied one bit 729 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 730 or ta2, ta2, SIMPL_ONE # set implied one bit 731/* 732 * Perform the addition. 733 */ 7345: 735 move t8, zero # no shifted bits (sticky reg) 736 beq t1, ta1, 4f # no shift needed 737 subu v0, t1, ta1 # v0 = difference of exponents 738 move v1, v0 # v1 = abs(difference) 739 bge v0, zero, 1f 740 negu v1 7411: 742 ble v1, SFRAC_BITS+2, 2f # is difference too great? 743 li t8, STICKYBIT # set the sticky bit 744 bge v0, zero, 1f # check which exp is larger 745 move t1, ta1 # result exp is FTs 746 move t2, zero # FSs fraction shifted is zero 747 b 4f 7481: 749 move ta2, zero # FTs fraction shifted is zero 750 b 4f 7512: 752 li t9, 32 # compute 32 - abs(exp diff) 753 subu t9, t9, v1 754 bgt v0, zero, 3f # if FS > FT, shift FTs frac 755 move t1, ta1 # FT > FS, result exp is FTs 756 sll t8, t2, t9 # save bits shifted out 757 srl t2, t2, v1 # shift FSs fraction 758 b 4f 7593: 760 sll t8, ta2, t9 # save bits shifted out 761 srl ta2, ta2, v1 # shift FTs fraction 7624: 763 bne t0, ta0, 1f # if signs differ, subtract 764 addu t2, t2, ta2 # add fractions 765 b norm_s 7661: 767 blt t2, ta2, 3f # subtract larger from smaller 768 bne t2, ta2, 2f # if same, result=0 769 move t1, zero # result=0 770 move t2, zero 771 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 772 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 773 or t0, t0, ta0 # compute result sign 774 b result_fs_s 7751: 776 and t0, t0, ta0 # compute result sign 777 b result_fs_s 7782: 779 sltu t9, zero, t8 # compute t2:zero - ta2:t8 780 subu t8, zero, t8 781 subu t2, t2, ta2 # subtract fractions 782 subu t2, t2, t9 # subtract barrow 783 b norm_s 7843: 785 move t0, ta0 # sign of result = FTs 786 sltu t9, zero, t8 # compute ta2:zero - t2:t8 787 subu t8, zero, t8 788 subu t2, ta2, t2 # subtract fractions 789 subu t2, t2, t9 # subtract barrow 790 b norm_s 791 792/* 793 * Double precision subtract. 794 */ 795sub_d: 796 jal _C_LABEL(get_ft_fs_d) 797 xor ta0, ta0, 1 # negate sign bit 798 b add_sub_d 799/* 800 * Double precision add. 801 */ 802add_d: 803 jal _C_LABEL(get_ft_fs_d) 804add_sub_d: 805 bne t1, DEXP_INF, 1f # is FS an infinity? 806 bne ta1, DEXP_INF, result_fs_d # if FT is not inf, result=FS 807 bne t2, zero, result_fs_d # if FS is NAN, result is FS 808 bne t3, zero, result_fs_d 809 bne ta2, zero, result_ft_d # if FT is NAN, result is FT 810 bne ta3, zero, result_ft_d 811 bne t0, ta0, invalid_d # both infinities same sign? 812 b result_fs_d # result is in FS 8131: 814 beq ta1, DEXP_INF, result_ft_d # if FT is inf, result=FT 815 bne t1, zero, 4f # is FS a denormalized num? 816 bne t2, zero, 1f # is FS zero? 817 beq t3, zero, 3f 8181: 819 bne ta1, zero, 2f # is FT a denormalized num? 820 bne ta2, zero, 1f 821 beq ta3, zero, result_fs_d # FT is zero, result=FS 8221: 823 jal _C_LABEL(renorm_fs_d) 824 jal _C_LABEL(renorm_ft_d) 825 b 5f 8262: 827 jal _C_LABEL(renorm_fs_d) 828 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 829 or ta2, ta2, DIMPL_ONE # set implied one bit 830 b 5f 8313: 832 bne ta1, zero, result_ft_d # if FT != 0, result=FT 833 bne ta2, zero, result_ft_d 834 bne ta3, zero, result_ft_d 835 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 836 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 837 or t0, t0, ta0 # compute result sign 838 b result_fs_d 8391: 840 and t0, t0, ta0 # compute result sign 841 b result_fs_d 8424: 843 bne ta1, zero, 2f # is FT a denormalized num? 844 bne ta2, zero, 1f 845 beq ta3, zero, result_fs_d # FT is zero, result=FS 8461: 847 subu t1, t1, DEXP_BIAS # unbias FS exponent 848 or t2, t2, DIMPL_ONE # set implied one bit 849 jal _C_LABEL(renorm_ft_d) 850 b 5f 8512: 852 subu t1, t1, DEXP_BIAS # unbias FS exponent 853 or t2, t2, DIMPL_ONE # set implied one bit 854 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 855 or ta2, ta2, DIMPL_ONE # set implied one bit 856/* 857 * Perform the addition. 858 */ 8595: 860 move t8, zero # no shifted bits (sticky reg) 861 beq t1, ta1, 4f # no shift needed 862 subu v0, t1, ta1 # v0 = difference of exponents 863 move v1, v0 # v1 = abs(difference) 864 bge v0, zero, 1f 865 negu v1 8661: 867 ble v1, DFRAC_BITS+2, 2f # is difference too great? 868 li t8, STICKYBIT # set the sticky bit 869 bge v0, zero, 1f # check which exp is larger 870 move t1, ta1 # result exp is FTs 871 move t2, zero # FSs fraction shifted is zero 872 move t3, zero 873 b 4f 8741: 875 move ta2, zero # FTs fraction shifted is zero 876 move ta3, zero 877 b 4f 8782: 879 li t9, 32 880 bge v0, zero, 3f # if FS > FT, shift FTs frac 881 move t1, ta1 # FT > FS, result exp is FTs 882 blt v1, t9, 1f # shift right by < 32? 883 subu v1, v1, t9 884 subu t9, t9, v1 885 sll t8, t2, t9 # save bits shifted out 886 sltu t9, zero, t3 # dont lose any one bits 887 or t8, t8, t9 # save sticky bit 888 srl t3, t2, v1 # shift FSs fraction 889 move t2, zero 890 b 4f 8911: 892 subu t9, t9, v1 893 sll t8, t3, t9 # save bits shifted out 894 srl t3, t3, v1 # shift FSs fraction 895 sll t9, t2, t9 # save bits shifted out of t2 896 or t3, t3, t9 # and put into t3 897 srl t2, t2, v1 898 b 4f 8993: 900 blt v1, t9, 1f # shift right by < 32? 901 subu v1, v1, t9 902 subu t9, t9, v1 903 sll t8, ta2, t9 # save bits shifted out 904 srl ta3, ta2, v1 # shift FTs fraction 905 move ta2, zero 906 b 4f 9071: 908 subu t9, t9, v1 909 sll t8, ta3, t9 # save bits shifted out 910 srl ta3, ta3, v1 # shift FTs fraction 911 sll t9, ta2, t9 # save bits shifted out of t2 912 or ta3, ta3, t9 # and put into t3 913 srl ta2, ta2, v1 9144: 915 bne t0, ta0, 1f # if signs differ, subtract 916 addu t3, t3, ta3 # add fractions 917 sltu t9, t3, ta3 # compute carry 918 addu t2, t2, ta2 # add fractions 919 addu t2, t2, t9 # add carry 920 b norm_d 9211: 922 blt t2, ta2, 3f # subtract larger from smaller 923 bne t2, ta2, 2f 924 bltu t3, ta3, 3f 925 bne t3, ta3, 2f # if same, result=0 926 move t1, zero # result=0 927 move t2, zero 928 move t3, zero 929 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 930 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity? 931 or t0, t0, ta0 # compute result sign 932 b result_fs_d 9331: 934 and t0, t0, ta0 # compute result sign 935 b result_fs_d 9362: 937 beq t8, zero, 1f # compute t2:t3:zero - ta2:ta3:t8 938 subu t8, zero, t8 939 sltu v0, t3, 1 # compute barrow out 940 subu t3, t3, 1 # subtract barrow 941 subu t2, t2, v0 9421: 943 sltu v0, t3, ta3 944 subu t3, t3, ta3 # subtract fractions 945 subu t2, t2, ta2 # subtract fractions 946 subu t2, t2, v0 # subtract barrow 947 b norm_d 9483: 949 move t0, ta0 # sign of result = FTs 950 beq t8, zero, 1f # compute ta2:ta3:zero - t2:t3:t8 951 subu t8, zero, t8 952 sltu v0, ta3, 1 # compute barrow out 953 subu ta3, ta3, 1 # subtract barrow 954 subu ta2, ta2, v0 9551: 956 sltu v0, ta3, t3 957 subu t3, ta3, t3 # subtract fractions 958 subu t2, ta2, t2 # subtract fractions 959 subu t2, t2, v0 # subtract barrow 960 b norm_d 961 962/* 963 * Single precision multiply. 964 */ 965mul_s: 966 jal _C_LABEL(get_ft_fs_s) 967 xor t0, t0, ta0 # compute sign of result 968 move ta0, t0 969 bne t1, SEXP_INF, 2f # is FS an infinity? 970 bne t2, zero, result_fs_s # if FS is a NAN, result=FS 971 bne ta1, SEXP_INF, 1f # FS is inf, is FT an infinity? 972 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT 973 b result_fs_s # result is infinity 9741: 975 bne ta1, zero, result_fs_s # inf * zero? if no, result=FS 976 bne ta2, zero, result_fs_s 977 b invalid_s # infinity * zero is invalid 9782: 979 bne ta1, SEXP_INF, 1f # FS != inf, is FT an infinity? 980 bne t1, zero, result_ft_s # zero * inf? if no, result=FT 981 bne t2, zero, result_ft_s 982 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT 983 b invalid_s # zero * infinity is invalid 9841: 985 bne t1, zero, 1f # is FS zero? 986 beq t2, zero, result_fs_s # result is zero 987 jal _C_LABEL(renorm_fs_s) 988 b 2f 9891: 990 subu t1, t1, SEXP_BIAS # unbias FS exponent 991 or t2, t2, SIMPL_ONE # set implied one bit 9922: 993 bne ta1, zero, 1f # is FT zero? 994 beq ta2, zero, result_ft_s # result is zero 995 jal _C_LABEL(renorm_ft_s) 996 b 2f 9971: 998 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 999 or ta2, ta2, SIMPL_ONE # set implied one bit 10002: 1001 addu t1, t1, ta1 # compute result exponent 1002 addu t1, t1, 9 # account for binary point 1003 multu t2, ta2 # multiply fractions 1004 mflo t8 1005 mfhi t2 1006 b norm_s 1007 1008/* 1009 * Double precision multiply. 1010 */ 1011mul_d: 1012 jal _C_LABEL(get_ft_fs_d) 1013 xor t0, t0, ta0 # compute sign of result 1014 move ta0, t0 1015 bne t1, DEXP_INF, 2f # is FS an infinity? 1016 bne t2, zero, result_fs_d # if FS is a NAN, result=FS 1017 bne t3, zero, result_fs_d 1018 bne ta1, DEXP_INF, 1f # FS is inf, is FT an infinity? 1019 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT 1020 bne ta3, zero, result_ft_d 1021 b result_fs_d # result is infinity 10221: 1023 bne ta1, zero, result_fs_d # inf * zero? if no, result=FS 1024 bne ta2, zero, result_fs_d 1025 bne ta3, zero, result_fs_d 1026 b invalid_d # infinity * zero is invalid 10272: 1028 bne ta1, DEXP_INF, 1f # FS != inf, is FT an infinity? 1029 bne t1, zero, result_ft_d # zero * inf? if no, result=FT 1030 bne t2, zero, result_ft_d # if FS is a NAN, result=FS 1031 bne t3, zero, result_ft_d 1032 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT 1033 bne ta3, zero, result_ft_d 1034 b invalid_d # zero * infinity is invalid 10351: 1036 bne t1, zero, 2f # is FS zero? 1037 bne t2, zero, 1f 1038 beq t3, zero, result_fs_d # result is zero 10391: 1040 jal _C_LABEL(renorm_fs_d) 1041 b 3f 10422: 1043 subu t1, t1, DEXP_BIAS # unbias FS exponent 1044 or t2, t2, DIMPL_ONE # set implied one bit 10453: 1046 bne ta1, zero, 2f # is FT zero? 1047 bne ta2, zero, 1f 1048 beq ta3, zero, result_ft_d # result is zero 10491: 1050 jal _C_LABEL(renorm_ft_d) 1051 b 3f 10522: 1053 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 1054 or ta2, ta2, DIMPL_ONE # set implied one bit 10553: 1056 addu t1, t1, ta1 # compute result exponent 1057 addu t1, t1, 12 # ??? 1058 multu t3, ta3 # multiply fractions (low * low) 1059 move ta0, t2 # free up t2,t3 for result 1060 move ta1, t3 1061 mflo a3 # save low order bits 1062 mfhi t8 1063 not v0, t8 1064 multu ta0, ta3 # multiply FS(high) * FT(low) 1065 mflo v1 1066 mfhi t3 # init low result 1067 sltu v0, v0, v1 # compute carry 1068 addu t8, v1 1069 multu ta1, ta2 # multiply FS(low) * FT(high) 1070 addu t3, t3, v0 # add carry 1071 not v0, t8 1072 mflo v1 1073 mfhi t2 1074 sltu v0, v0, v1 1075 addu t8, v1 1076 multu ta0, ta2 # multiply FS(high) * FT(high) 1077 addu t3, v0 1078 not v1, t3 1079 sltu v1, v1, t2 1080 addu t3, t2 1081 not v0, t3 1082 mfhi t2 1083 addu t2, v1 1084 mflo v1 1085 sltu v0, v0, v1 1086 addu t2, v0 1087 addu t3, v1 1088 sltu a3, zero, a3 # reduce t8,a3 to just t8 1089 or t8, a3 1090 b norm_d 1091 1092/* 1093 * Single precision divide. 1094 */ 1095div_s: 1096 jal _C_LABEL(get_ft_fs_s) 1097 xor t0, t0, ta0 # compute sign of result 1098 move ta0, t0 1099 bne t1, SEXP_INF, 1f # is FS an infinity? 1100 bne t2, zero, result_fs_s # if FS is NAN, result is FS 1101 bne ta1, SEXP_INF, result_fs_s # is FT an infinity? 1102 bne ta2, zero, result_ft_s # if FT is NAN, result is FT 1103 b invalid_s # infinity/infinity is invalid 11041: 1105 bne ta1, SEXP_INF, 1f # is FT an infinity? 1106 bne ta2, zero, result_ft_s # if FT is NAN, result is FT 1107 move t1, zero # x / infinity is zero 1108 move t2, zero 1109 b result_fs_s 11101: 1111 bne t1, zero, 2f # is FS zero? 1112 bne t2, zero, 1f 1113 bne ta1, zero, result_fs_s # FS=zero, is FT zero? 1114 beq ta2, zero, invalid_s # 0 / 0 1115 b result_fs_s # result = zero 11161: 1117 jal _C_LABEL(renorm_fs_s) 1118 b 3f 11192: 1120 subu t1, t1, SEXP_BIAS # unbias FS exponent 1121 or t2, t2, SIMPL_ONE # set implied one bit 11223: 1123 bne ta1, zero, 2f # is FT zero? 1124 bne ta2, zero, 1f 1125 or a2, a2, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0 1126 and v0, a2, MIPS_FPU_ENABLE_DIV0 # trap enabled? 1127 bne v0, zero, fpe_trap 1128#ifdef SOFTFLOAT 1129 lw t1, _C_LABEL(curpcb) # get pcb of current process 1130 #nop 1131 sw a2, U_PCB_FPREGS+FRAME_FSR(t1) 1132#else 1133 ctc1 a2, MIPS_FPU_CSR # save exceptions 1134#endif 1135 li t1, SEXP_INF # result is infinity 1136 move t2, zero 1137 b result_fs_s 11381: 1139 jal _C_LABEL(renorm_ft_s) 1140 b 3f 11412: 1142 subu ta1, ta1, SEXP_BIAS # unbias FT exponent 1143 or ta2, ta2, SIMPL_ONE # set implied one bit 11443: 1145 subu t1, t1, ta1 # compute exponent 1146 subu t1, t1, 3 # compensate for result position 1147 li v0, SFRAC_BITS+3 # number of bits to divide 1148 move t8, t2 # init dividend 1149 move t2, zero # init result 11501: 1151 bltu t8, ta2, 3f # is dividend >= divisor? 11522: 1153 subu t8, t8, ta2 # subtract divisor from dividend 1154 or t2, t2, 1 # remember that we did 1155 bne t8, zero, 3f # if not done, continue 1156 sll t2, t2, v0 # shift result to final position 1157 b norm_s 11583: 1159 sll t8, t8, 1 # shift dividend 1160 sll t2, t2, 1 # shift result 1161 subu v0, v0, 1 # are we done? 1162 bne v0, zero, 1b # no, continue 1163 b norm_s 1164 1165/* 1166 * Double precision divide. 1167 */ 1168div_d: 1169 jal _C_LABEL(get_ft_fs_d) 1170 xor t0, t0, ta0 # compute sign of result 1171 move ta0, t0 1172 bne t1, DEXP_INF, 1f # is FS an infinity? 1173 bne t2, zero, result_fs_d # if FS is NAN, result is FS 1174 bne t3, zero, result_fs_d 1175 bne ta1, DEXP_INF, result_fs_d # is FT an infinity? 1176 bne ta2, zero, result_ft_d # if FT is NAN, result is FT 1177 bne ta3, zero, result_ft_d 1178 b invalid_d # infinity/infinity is invalid 11791: 1180 bne ta1, DEXP_INF, 1f # is FT an infinity? 1181 bne ta2, zero, result_ft_d # if FT is NAN, result is FT 1182 bne ta3, zero, result_ft_d 1183 move t1, zero # x / infinity is zero 1184 move t2, zero 1185 move t3, zero 1186 b result_fs_d 11871: 1188 bne t1, zero, 2f # is FS zero? 1189 bne t2, zero, 1f 1190 bne t3, zero, 1f 1191 bne ta1, zero, result_fs_d # FS=zero, is FT zero? 1192 bne ta2, zero, result_fs_d 1193 beq ta3, zero, invalid_d # 0 / 0 1194 b result_fs_d # result = zero 11951: 1196 jal _C_LABEL(renorm_fs_d) 1197 b 3f 11982: 1199 subu t1, t1, DEXP_BIAS # unbias FS exponent 1200 or t2, t2, DIMPL_ONE # set implied one bit 12013: 1202 bne ta1, zero, 2f # is FT zero? 1203 bne ta2, zero, 1f 1204 bne ta3, zero, 1f 1205 or a2, a2, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0 1206 and v0, a2, MIPS_FPU_ENABLE_DIV0 # trap enabled? 1207 bne v0, zero, fpe_trap 1208#ifdef SOFTFLOAT 1209 lw t1, _C_LABEL(curpcb) # get pcb of current process 1210 #nop 1211 sw a2, U_PCB_FPREGS+FRAME_FSR(t1) 1212#else 1213 ctc1 a2, MIPS_FPU_CSR # save exceptions 1214#endif 1215 li t1, DEXP_INF # result is infinity 1216 move t2, zero 1217 move t3, zero 1218 b result_fs_d 12191: 1220 jal _C_LABEL(renorm_ft_d) 1221 b 3f 12222: 1223 subu ta1, ta1, DEXP_BIAS # unbias FT exponent 1224 or ta2, ta2, DIMPL_ONE # set implied one bit 12253: 1226 subu t1, t1, ta1 # compute exponent 1227 subu t1, t1, 3 # compensate for result position 1228 li v0, DFRAC_BITS+3 # number of bits to divide 1229 move t8, t2 # init dividend 1230 move t9, t3 1231 move t2, zero # init result 1232 move t3, zero 12331: 1234 bltu t8, ta2, 3f # is dividend >= divisor? 1235 bne t8, ta2, 2f 1236 bltu t9, ta3, 3f 12372: 1238 sltu v1, t9, ta3 # subtract divisor from dividend 1239 subu t9, t9, ta3 1240 subu t8, t8, ta2 1241 subu t8, t8, v1 1242 or t3, t3, 1 # remember that we did 1243 bne t8, zero, 3f # if not done, continue 1244 bne t9, zero, 3f 1245 li v1, 32 # shift result to final position 1246 blt v0, v1, 2f # shift < 32 bits? 1247 subu v0, v0, v1 # shift by > 32 bits 1248 sll t2, t3, v0 # shift upper part 1249 move t3, zero 1250 b norm_d 12512: 1252 subu v1, v1, v0 # shift by < 32 bits 1253 sll t2, t2, v0 # shift upper part 1254 srl t9, t3, v1 # save bits shifted out 1255 or t2, t2, t9 # and put into upper part 1256 sll t3, t3, v0 1257 b norm_d 12583: 1259 sll t8, t8, 1 # shift dividend 1260 srl v1, t9, 31 # save bit shifted out 1261 or t8, t8, v1 # and put into upper part 1262 sll t9, t9, 1 1263 sll t2, t2, 1 # shift result 1264 srl v1, t3, 31 # save bit shifted out 1265 or t2, t2, v1 # and put into upper part 1266 sll t3, t3, 1 1267 subu v0, v0, 1 # are we done? 1268 bne v0, zero, 1b # no, continue 1269 sltu v0, zero, t9 # be sure to save any one bits 1270 or t8, t8, v0 # from the lower remainder 1271 b norm_d 1272 1273#ifdef MIPS3_PLUS 1274sqrt_s: 1275 jal _C_LABEL(get_fs_s) 1276 1277 /* Take care of zero, negative, inf, and NaN special cases */ 1278 or v0, t1, t2 # sqrt(+-0) == +-0 1279 beq v0, zero, result_fs_s # ... 1280 bne t0, zero, 1f # sqrt(-val) == sNaN 1281 bne t1, SEXP_INF, 2f # skip forward if not infinity 1282 b result_fs_s # sqrt(NaN,+inf) == itself 12831: move t0, zero # result is a quiet NAN 1284 li t1, SEXP_INF # sqrt(-inf,-val) == sNaN 1285 li t2, SQUIET_NAN 1286 b result_fs_s 12872: 1288 /* normalize FS if needed */ 1289 bne t1, zero, 2f 1290 jal _C_LABEL(renorm_fs_s) 12912: and t2, t2, (SIMPL_ONE-1) # ix &= 0x007fffff; 1292 or t2, t2, SIMPL_ONE # ix |= 0x00800000; 1293 and v0, t1, 1 # if (m & 1) 1294 beq v0, zero, 1f # ... 1295 add t2, t2, t2 # ix += ix; 12961: sra t1, t1, 1 # m = m / 2; 1297 1298 /* generate sqrt(FS) bit by bit */ 1299 add t2, t2, t2 # ix += ix; 1300 move ta0, zero # q = 0; (result) 1301 li t8, SIMPL_ONE<<1 # r = 0x01000000; 1302 move ta2, zero # s = 0; 13031: beq t8, zero, 3f # while (r != 0) { 1304 add t9, ta2, t8 # t = s + r; 1305 bgt t9, t2, 2f # if (t <= ix) 1306 add ta2, t9, t8 # s = t + r; 1307 sub t2, t2, t9 # ix -= t; 1308 add ta0, ta0, t8 # q += r; 13092: add t2, t2, t2 # ix += ix; 1310 srl t8, t8, 1 # r >>= 1; 1311 b 1b # } 13123: 1313 /* rounding -- all mips rounding modes use the same rounding here */ 1314 beq t2, zero, 1f # if (ix != 0) 1315 and v0, ta0, 1 # q += q&1; 1316 add ta0, ta0, v0 # ... 1317 1318 /* calculate result */ 13191: srl t2, ta0, 1 # ix = (q >> 1); 1320 add t1, t1, SEXP_BIAS # m += 127; (re-bias) 1321 li v1, SIMPL_ONE 1322 and v0, t2, v1 # keep extra exponent bit 1323 bne v0, zero, 1f # if it is there. 1324 sub t1, t1, 1 # ... 13251: 1326 nor v1, v1, v1 # ~SIMP_ONE 1327 and t2, t2, v1 # ix &= ~SIMPL_ONE 1328 b result_fs_s # store result (already normal) 1329 1330sqrt_d: 1331 jal _C_LABEL(get_fs_d) 1332 1333 /* Take care of zero, negative, inf, and NaN special cases */ 1334 or v0, t1, t2 # sqrt(+-0) == +- 0 1335 or v0, v0, t3 # ... 1336 beq v0, zero, result_fs_d # ... 1337 bne t0, zero, 1f # sqrt(-val) == sNaN 1338 bne t1, DEXP_INF, 2f # skip forward if not infinity 1339 b result_fs_d # sqrt(NaN,+inf) == itself 13401: move t0, zero # sqrt(-inf,-val) == sNaN 1341 li t1, DEXP_INF 1342 li t2, DQUIET_NAN0 1343 li t3, DQUIET_NAN1 1344 b result_fs_d 13452: 1346 /* normalize FS if needed */ 1347 bne t1, zero, 2f 1348 jal _C_LABEL(renorm_fs_d) 13492: and t2, t2, (DIMPL_ONE-1) # ix0 &= 0x000fffff 1350 or t2, t2, DIMPL_ONE # ix0 |= 0x00100000 1351 and v0, t1, 1 # if (m & 1) 1352 beq v0, zero, 1f # ... 1353 add t2, t2, t2 # ix0 += ix0 1354 srl v0, t3, 31 # ix0 += (ix1&sign)>>31) 1355 and v0, v0, 1 # ... 1356 add t2, t2, v0 # ... 1357 addu t3, t3, t3 # ix1 += ix1; 13581: sra t1, t1, 1 # m = m / 2; 1359 1360 /* generate sqrt(FS) bit by bit -- first upper */ 1361 addu t2, t2, t2 # ix0 += ix0; 1362 srl v0, t3, 31 # ix0 += (ix1&sign)>>31) 1363 and v0, v0, 1 # ... 1364 add t2, t2, v0 # ... 1365 addu t3, t3, t3 # ix1 += ix1; 1366 1367 move ta0, zero # q = 0; (result) 1368 move ta1, zero # q1 = 0; (result) 1369 move ta2, zero # s0 = 0; 1370 move ta3, zero # s1 = 0; 1371 li t8, DIMPL_ONE<<1 # t = 0x00200000; 13721: beq t8, zero, 3f # while (r != 0) { 1373 add t9, ta2, t8 # t = s0+r; 1374 bgt t9, t2, 2f # if (t <= ix0) 1375 add ta2, t9, t8 # s0 = t + r; 1376 sub t2, t2, t9 # ix0 -= t; 1377 add ta0, ta0, t8 # q += r; 13782: add t2, t2, t2 # ix0 += ix0; 1379 srl v0, t3, 31 # ix0 += (ix1&sign)>>31) 1380 and v0, v0, 1 # ... 1381 add t2, t2, v0 # ... 1382 addu t3, t3, t3 # ix1 += ix1; 1383 srl t8, t8, 1 # r >>= 1; 1384 b 1b # } 13853: 1386 /* then lower bits */ 1387 li t8, 1<<31 # r = sign; 13881: beq t8, zero, 4f # while (r != 0) { 1389 addu v1, ta3, t8 # t1 = s1 + r; 1390 move t9, ta2 # t = s0; 1391 blt t9, t2, 2f # if ( (t<ix0) || 1392 bne t9, t2, 3f # ((t == ix0) && 1393 bgtu v1, t3, 3f # (t1 <= ix1))) 13942: addu ta3, v1, t8 # s1 = t1 + r; 1395 srl v0, v1, 31 # if (((t1&sign)==sign) && 1396 and v0, v0, 1 # ... 1397 beq v0, zero, 2f # ... 1398 srl v0, ta3, 31 # (s1&sign) == 0) 1399 and v0, v0, 1 # ... 1400 bne v0, zero, 2f # ... 1401 add ta2, ta2, 1 # s0 += 1; 14022: sub t2, t2, t9 # ix0 -= t; 1403 bgeu t3, v1, 2f # if (ix1 < t1) 1404 sub t2, t2, 1 # ix0 -= 1; 14052: subu t3, t3, v1 # ix1 -= t1; 1406 addu ta1, ta1, t8 # q1 += r; 14073: add t2, t2, t2 # ix0 += ix0; 1408 srl v0, t3, 31 # ix0 += (ix1&sign)>>31) 1409 and v0, v0, 1 # ... 1410 add t2, t2, v0 # ... 1411 addu t3, t3, t3 # ix1 += ix1; 1412 srl t8, t8, 1 # r >>= 1; 1413 b 1b # } 14144: 1415 1416 /* rounding -- all mips rounding modes use the same rounding here */ 1417 or v0, t2, t3 # if (ix0 | ix1) 1418 beq v0, zero, 2f # ... 1419 li v0, 0xffffffff # if (q1 == 0xffffffff) 1420 and v1, t2, v0 # ... 1421 bne v1, v0, 1f # ... 1422 move ta1, zero # q1 = 0; 1423 add ta0, ta0, 1 # q += 1; 1424 b 2f # else 14251: and v0, ta1, 1 # q1 += q1 & 1; 1426 addu ta1, ta1, v0 # ... 1427 1428 /* calculate result */ 14292: srl t2, ta0, 1 # ix0 = q >> 1; 1430 srl t3, ta1, 1 # ix1 = q1 >> 1; 1431 and v0, ta0, 1 # if ((q & 1) == 1) 1432 beq v0, zero, 1f # ... 1433 or t3, (1<<31) # ix1 |= sign; 14341: add t1, t1, DEXP_BIAS # m += 1023; 1435 li v1, DIMPL_ONE 1436 and v0, t2, v1 # keep extra exponent bit 1437 bne v0, zero, 1f # if it is there. 1438 sub t1, t1, 1 # ... 14391: 1440 nor v1, v1, v1 # ~DIMPL_ONE 1441 and t2, t2, v1 # ix0 &= ~DIMPL_ONE 1442 b result_fs_d # store result (already normal) 1443#endif /* MIPS3_PLUS */ 1444 1445/* 1446 * Single precision absolute value. 1447 */ 1448abs_s: 1449 jal _C_LABEL(get_fs_s) 1450 move t0, zero # set sign positive 1451 b result_fs_s 1452 1453/* 1454 * Double precision absolute value. 1455 */ 1456abs_d: 1457 jal _C_LABEL(get_fs_d) 1458 move t0, zero # set sign positive 1459 b result_fs_d 1460 1461/* 1462 * Single precision move. 1463 */ 1464mov_s: 1465 jal _C_LABEL(get_fs_s) 1466 b result_fs_s 1467 1468/* 1469 * Double precision move. 1470 */ 1471mov_d: 1472 jal _C_LABEL(get_fs_d) 1473 b result_fs_d 1474 1475/* 1476 * Single precision negate. 1477 */ 1478neg_s: 1479 jal _C_LABEL(get_fs_s) 1480 xor t0, t0, 1 # reverse sign 1481 b result_fs_s 1482 1483/* 1484 * Double precision negate. 1485 */ 1486neg_d: 1487 jal _C_LABEL(get_fs_d) 1488 xor t0, t0, 1 # reverse sign 1489 b result_fs_d 1490 1491/* 1492 * Single precision mips2 rounding. Explicit case of cvt_w_s. 1493 */ 1494round_w_s: 1495 li v1,0 1496 b _cvt_w_s 1497trunc_w_s: 1498 li v1,1 1499 b _cvt_w_s 1500ceil_w_s: 1501 li v1,2 1502 b _cvt_w_s 1503floor_w_s: 1504 li v1,3 1505 b _cvt_w_s 1506 1507/* 1508 * Double precision mips2 rounding. Explicit case of cvt_w_d. 1509 */ 1510round_w_d: 1511 li v1,0 1512 b _cvt_w_d 1513trunc_w_d: 1514 li v1,1 1515 b _cvt_w_d 1516ceil_w_d: 1517 li v1,2 1518 b _cvt_w_d 1519floor_w_d: 1520 li v1,3 1521 b _cvt_w_d 1522 1523/* 1524 * Convert double to single. 1525 */ 1526cvt_s_d: 1527 jal _C_LABEL(get_fs_d) 1528 bne t1, DEXP_INF, 1f # is FS an infinity? 1529 li t1, SEXP_INF # convert to single 1530 sll t2, t2, 3 # convert D fraction to S 1531 srl t8, t3, 32 - 3 1532 or t2, t2, t8 1533 b result_fs_s 15341: 1535 bne t1, zero, 2f # is FS zero? 1536 bne t2, zero, 1f 1537 beq t3, zero, result_fs_s # result=0 15381: 1539 jal _C_LABEL(renorm_fs_d) 1540 subu t1, t1, 3 # correct exp for shift below 1541 b 3f 15422: 1543 subu t1, t1, DEXP_BIAS # unbias exponent 1544 or t2, t2, DIMPL_ONE # add implied one bit 15453: 1546 sll t2, t2, 3 # convert D fraction to S 1547 srl t8, t3, 32 - 3 1548 or t2, t2, t8 1549 sll t8, t3, 3 1550 b norm_noshift_s 1551 1552/* 1553 * Convert integer to single. 1554 */ 1555cvt_s_w: 1556 jal _C_LABEL(get_fs_int) 1557 bne t2, zero, 1f # check for zero 1558 move t1, zero 1559 b result_fs_s 1560/* 1561 * Find out how many leading zero bits are in t2 and put in t9. 1562 */ 15631: 1564 move v0, t2 1565 move t9, zero 1566 srl v1, v0, 16 1567 bne v1, zero, 1f 1568 addu t9, 16 1569 sll v0, 16 15701: 1571 srl v1, v0, 24 1572 bne v1, zero, 1f 1573 addu t9, 8 1574 sll v0, 8 15751: 1576 srl v1, v0, 28 1577 bne v1, zero, 1f 1578 addu t9, 4 1579 sll v0, 4 15801: 1581 srl v1, v0, 30 1582 bne v1, zero, 1f 1583 addu t9, 2 1584 sll v0, 2 15851: 1586 srl v1, v0, 31 1587 bne v1, zero, 1f 1588 addu t9, 1 1589/* 1590 * Now shift t2 the correct number of bits. 1591 */ 15921: 1593 subu t9, t9, SLEAD_ZEROS # dont count leading zeros 1594 li t1, 23 # init exponent 1595 subu t1, t1, t9 # compute exponent 1596 beq t9, zero, 1f 1597 li v0, 32 1598 blt t9, zero, 2f # if shift < 0, shift right 1599 subu v0, v0, t9 1600 sll t2, t2, t9 # shift left 16011: 1602 add t1, t1, SEXP_BIAS # bias exponent 1603 and t2, t2, ~SIMPL_ONE # clear implied one bit 1604 b result_fs_s 16052: 1606 negu t9 # shift right by t9 1607 subu v0, v0, t9 1608 sll t8, t2, v0 # save bits shifted out 1609 srl t2, t2, t9 1610 b norm_noshift_s 1611 1612/* 1613 * Convert single to double. 1614 */ 1615cvt_d_s: 1616 jal _C_LABEL(get_fs_s) 1617 move t3, zero 1618 bne t1, SEXP_INF, 1f # is FS an infinity? 1619 li t1, DEXP_INF # convert to double 1620 b result_fs_d 16211: 1622 bne t1, zero, 2f # is FS denormalized or zero? 1623 beq t2, zero, result_fs_d # is FS zero? 1624 jal _C_LABEL(renorm_fs_s) 1625 move t8, zero 1626 b norm_d 16272: 1628 addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly 1629 sll t3, t2, 32 - 3 # convert S fraction to D 1630 srl t2, t2, 3 1631 b result_fs_d 1632 1633/* 1634 * Convert integer to double. 1635 */ 1636cvt_d_w: 1637 jal _C_LABEL(get_fs_int) 1638 bne t2, zero, 1f # check for zero 1639 move t1, zero # result=0 1640 move t3, zero 1641 b result_fs_d 1642/* 1643 * Find out how many leading zero bits are in t2 and put in t9. 1644 */ 16451: 1646 move v0, t2 1647 move t9, zero 1648 srl v1, v0, 16 1649 bne v1, zero, 1f 1650 addu t9, 16 1651 sll v0, 16 16521: 1653 srl v1, v0, 24 1654 bne v1, zero, 1f 1655 addu t9, 8 1656 sll v0, 8 16571: 1658 srl v1, v0, 28 1659 bne v1, zero, 1f 1660 addu t9, 4 1661 sll v0, 4 16621: 1663 srl v1, v0, 30 1664 bne v1, zero, 1f 1665 addu t9, 2 1666 sll v0, 2 16671: 1668 srl v1, v0, 31 1669 bne v1, zero, 1f 1670 addu t9, 1 1671/* 1672 * Now shift t2 the correct number of bits. 1673 */ 16741: 1675 subu t9, t9, DLEAD_ZEROS # dont count leading zeros 1676 li t1, DEXP_BIAS + 20 # init exponent 1677 subu t1, t1, t9 # compute exponent 1678 beq t9, zero, 1f 1679 li v0, 32 1680 blt t9, zero, 2f # if shift < 0, shift right 1681 subu v0, v0, t9 1682 sll t2, t2, t9 # shift left 16831: 1684 and t2, t2, ~DIMPL_ONE # clear implied one bit 1685 move t3, zero 1686 b result_fs_d 16872: 1688 negu t9 # shift right by t9 1689 subu v0, v0, t9 1690 sll t3, t2, v0 1691 srl t2, t2, t9 1692 and t2, t2, ~DIMPL_ONE # clear implied one bit 1693 b result_fs_d 1694 1695/* 1696 * Convert single to integer. 1697 */ 1698cvt_w_s: 1699 and v1, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 1700_cvt_w_s: 1701 jal _C_LABEL(get_fs_s) 1702 bne t1, SEXP_INF, 1f # is FS an infinity? 1703 bne t2, zero, invalid_w # invalid conversion 17041: 1705 bne t1, zero, 1f # is FS zero? 1706 beq t2, zero, result_fs_w # result is zero 1707 move t2, zero # result is an inexact zero 1708 b inexact_w 17091: 1710 subu t1, t1, SEXP_BIAS # unbias exponent 1711 or t2, t2, SIMPL_ONE # add implied one bit 1712 sll t3, t2, 32 - 3 # convert S fraction to D 1713 srl t2, t2, 3 1714 b cvt_w 1715 1716/* 1717 * Convert double to integer. 1718 */ 1719cvt_w_d: 1720 and v1, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 1721_cvt_w_d: 1722 jal _C_LABEL(get_fs_d) 1723 bne t1, DEXP_INF, 1f # is FS an infinity? 1724 bne t2, zero, invalid_w # invalid conversion 1725 bne t3, zero, invalid_w # invalid conversion 17261: 1727 bne t1, zero, 2f # is FS zero? 1728 bne t2, zero, 1f 1729 beq t3, zero, result_fs_w # result is zero 17301: 1731 move t2, zero # result is an inexact zero 1732 b inexact_w 17332: 1734 subu t1, t1, DEXP_BIAS # unbias exponent 1735 or t2, t2, DIMPL_ONE # add implied one bit 1736cvt_w: 1737#if 0 1738 blt t1, WEXP_MIN, underflow_w # is exponent too small? 1739#else 1740 bge t1, WEXP_MIN, 3f # is exponent too small? 1741 beq v1, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1742 beq v1, MIPS_FPU_ROUND_RM, 2f # round to -infinity 1743 1744 move t2, zero 1745 b result_fs_w 17461: 1747 xori t2, t0, 1 1748 b result_fs_w 17492: 1750 sll t2, t0, 31 1751 sra t2, t2, 31 1752 b result_fs_w 1753 17543: 1755#endif 1756 li v0, WEXP_MAX+1 1757 bgt t1, v0, overflow_w # is exponent too large? 1758 bne t1, v0, 1f # special check for INT_MIN 1759 beq t0, zero, overflow_w # if positive, overflow 1760 bne t2, DIMPL_ONE, overflow_w 1761 bne t3, zero, overflow_w 1762 li t2, INT_MIN # result is INT_MIN 1763 b result_fs_w 17641: 1765 subu v0, t1, 20 # compute amount to shift 1766 beq v0, zero, 2f # is shift needed? 1767 li v1, 32 1768 blt v0, zero, 1f # if shift < 0, shift right 1769 subu v1, v1, v0 # shift left 1770 sll t2, t2, v0 1771 srl t9, t3, v1 # save bits shifted out of t3 1772 or t2, t2, t9 # and put into t2 1773 sll t3, t3, v0 # shift FSs fraction 1774 b 2f 17751: 1776 negu v0 # shift right by v0 1777 subu v1, v1, v0 1778 sll t8, t3, v1 # save bits shifted out 1779 sltu t8, zero, t8 # dont lose any ones 1780 srl t3, t3, v0 # shift FSs fraction 1781 or t3, t3, t8 1782 sll t9, t2, v1 # save bits shifted out of t2 1783 or t3, t3, t9 # and put into t3 1784 srl t2, t2, v0 1785/* 1786 * round result (t0 is sign, t2 is integer part, t3 is fractional part). 1787 */ 17882: 1789 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 1790 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 1791 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 1792 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 1793 beq t0, zero, 5f # if sign is positive, truncate 1794 b 2f 17951: 1796 bne t0, zero, 5f # if sign is negative, truncate 17972: 1798 beq t3, zero, 5f # if no fraction bits, continue 1799 addu t2, t2, 1 # add rounding bit 1800 blt t2, zero, overflow_w # overflow? 1801 b 5f 18023: 1803 li v0, GUARDBIT # load guard bit for rounding 1804 addu v0, v0, t3 # add remainder 1805 sltu v1, v0, t3 # compute carry out 1806 beq v1, zero, 4f # if no carry, continue 1807 addu t2, t2, 1 # add carry to result 1808 blt t2, zero, overflow_w # overflow? 18094: 1810 bne v0, zero, 5f # if rounded remainder is zero 1811 and t2, t2, ~1 # clear LSB (round to nearest) 18125: 1813 beq t0, zero, 1f # result positive? 1814 negu t2 # convert to negative integer 18151: 1816 beq t3, zero, result_fs_w # is result exact? 1817/* 1818 * Handle inexact exception. 1819 */ 1820inexact_w: 1821 or a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 1822 and v0, a2, MIPS_FPU_ENABLE_INEXACT 1823 bne v0, zero, fpe_trap 1824#ifdef SOFTFLOAT 1825 lw v0, _C_LABEL(curpcb) # get pcb of current process 1826 #nop 1827 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 1828#else 1829 ctc1 a2, MIPS_FPU_CSR # save exceptions 1830#endif 1831 b result_fs_w 1832 1833/* 1834 * Conversions to integer which overflow will trap (if enabled), 1835 * or generate an inexact trap (if enabled), 1836 * or generate an invalid exception. 1837 */ 1838overflow_w: 1839 or a2, a2, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW 1840 and v0, a2, MIPS_FPU_ENABLE_OVERFLOW 1841 bne v0, zero, fpe_trap 1842 and v0, a2, MIPS_FPU_ENABLE_INEXACT 1843 bne v0, zero, inexact_w # inexact traps enabled? 1844 b invalid_w 1845 1846/* 1847 * Conversions to integer which underflow will trap (if enabled), 1848 * or generate an inexact trap (if enabled), 1849 * or generate an invalid exception. 1850 */ 1851underflow_w: 1852 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 1853 and v0, a2, MIPS_FPU_ENABLE_UNDERFLOW 1854 bne v0, zero, fpe_trap 1855 and v0, a2, MIPS_FPU_ENABLE_INEXACT 1856 bne v0, zero, inexact_w # inexact traps enabled? 1857 b invalid_w 1858 1859/* 1860 * Compare single. 1861 */ 1862cmp_s: 1863 jal _C_LABEL(get_cmp_s) 1864 bne t1, SEXP_INF, 1f # is FS an infinity? 1865 bne t2, zero, unordered # FS is a NAN 18661: 1867 bne ta1, SEXP_INF, 2f # is FT an infinity? 1868 bne ta2, zero, unordered # FT is a NAN 18692: 1870 sll t1, t1, 23 # reassemble exp & frac 1871 or t1, t1, t2 1872 sll ta1, ta1, 23 # reassemble exp & frac 1873 or ta1, ta1, ta2 1874 beq t0, zero, 1f # is FS positive? 1875 negu t1 18761: 1877 beq ta0, zero, 1f # is FT positive? 1878 negu ta1 18791: 1880 li v0, COND_LESS 1881 blt t1, ta1, test_cond # is FS < FT? 1882 li v0, COND_EQUAL 1883 beq t1, ta1, test_cond # is FS == FT? 1884 move v0, zero # FS > FT 1885 b test_cond 1886 1887/* 1888 * Compare double. 1889 */ 1890cmp_d: 1891 jal _C_LABEL(get_cmp_d) 1892 bne t1, DEXP_INF, 1f # is FS an infinity? 1893 bne t2, zero, unordered 1894 bne t3, zero, unordered # FS is a NAN 18951: 1896 bne ta1, DEXP_INF, 2f # is FT an infinity? 1897 bne ta2, zero, unordered 1898 bne ta3, zero, unordered # FT is a NAN 18992: 1900 sll t1, t1, 20 # reassemble exp & frac 1901 or t1, t1, t2 1902 sll ta1, ta1, 20 # reassemble exp & frac 1903 or ta1, ta1, ta2 1904 beq t0, zero, 1f # is FS positive? 1905 not t3 # negate t1,t3 1906 not t1 1907 addu t3, t3, 1 1908 seq v0, t3, zero # compute carry 1909 addu t1, t1, v0 19101: 1911 beq ta0, zero, 1f # is FT positive? 1912 not ta3 # negate ta1,ta3 1913 not ta1 1914 addu ta3, ta3, 1 1915 seq v0, ta3, zero # compute carry 1916 addu ta1, ta1, v0 19171: 1918 li v0, COND_LESS 1919 blt t1, ta1, test_cond # is FS(MSW) < FT(MSW)? 1920 move v0, zero 1921 bne t1, ta1, test_cond # is FS(MSW) > FT(MSW)? 1922 li v0, COND_LESS 1923 bltu t3, ta3, test_cond # is FS(LSW) < FT(LSW)? 1924 li v0, COND_EQUAL 1925 beq t3, ta3, test_cond # is FS(LSW) == FT(LSW)? 1926 move v0, zero # FS > FT 1927test_cond: 1928 and v0, v0, a0 # condition match instruction? 1929set_cond: 1930 bne v0, zero, 1f 1931 and a2, a2, ~MIPS_FPU_COND_BIT # clear condition bit 1932 b 2f 19331: 1934 or a2, a2, MIPS_FPU_COND_BIT # set condition bit 19352: 1936#ifdef SOFTFLOAT 1937 lw v0, _C_LABEL(curpcb) # get pcb of current process 1938 #nop 1939 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 1940#else 1941 ctc1 a2, MIPS_FPU_CSR # save condition bit 1942#endif 1943 b done 1944 1945unordered: 1946 and v0, a0, COND_UNORDERED # this cmp match unordered? 1947 bne v0, zero, 1f 1948 and a2, a2, ~MIPS_FPU_COND_BIT # clear condition bit 1949 b 2f 19501: 1951 or a2, a2, MIPS_FPU_COND_BIT # set condition bit 19522: 1953 and v0, a0, COND_SIGNAL 1954 beq v0, zero, 1f # is this a signaling cmp? 1955 or a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 1956 and v0, a2, MIPS_FPU_ENABLE_INVALID 1957 bne v0, zero, fpe_trap 19581: 1959#ifdef SOFTFLOAT 1960 lw v0, _C_LABEL(curpcb) # get pcb of current process 1961 #nop 1962 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 1963#else 1964 ctc1 a2, MIPS_FPU_CSR # save condition bit 1965#endif 1966 b done 1967 1968/* 1969 * Determine the amount to shift the fraction in order to restore the 1970 * normalized position. After that, round and handle exceptions. 1971 */ 1972norm_s: 1973 move v0, t2 1974 move t9, zero # t9 = num of leading zeros 1975 bne t2, zero, 1f 1976 move v0, t8 1977 addu t9, 32 19781: 1979 srl v1, v0, 16 1980 bne v1, zero, 1f 1981 addu t9, 16 1982 sll v0, 16 19831: 1984 srl v1, v0, 24 1985 bne v1, zero, 1f 1986 addu t9, 8 1987 sll v0, 8 19881: 1989 srl v1, v0, 28 1990 bne v1, zero, 1f 1991 addu t9, 4 1992 sll v0, 4 19931: 1994 srl v1, v0, 30 1995 bne v1, zero, 1f 1996 addu t9, 2 1997 sll v0, 2 19981: 1999 srl v1, v0, 31 2000 bne v1, zero, 1f 2001 addu t9, 1 2002/* 2003 * Now shift t2,t8 the correct number of bits. 2004 */ 20051: 2006 subu t9, t9, SLEAD_ZEROS # dont count leading zeros 2007 subu t1, t1, t9 # adjust the exponent 2008 beq t9, zero, norm_noshift_s 2009 li v1, 32 2010 blt t9, zero, 1f # if shift < 0, shift right 2011 subu v1, v1, t9 2012 sll t2, t2, t9 # shift t2,t8 left 2013 srl v0, t8, v1 # save bits shifted out 2014 or t2, t2, v0 2015 sll t8, t8, t9 2016 b norm_noshift_s 20171: 2018 negu t9 # shift t2,t8 right by t9 2019 subu v1, v1, t9 2020 sll v0, t8, v1 # save bits shifted out 2021 sltu v0, zero, v0 # be sure to save any one bits 2022 srl t8, t8, t9 2023 or t8, t8, v0 2024 sll v0, t2, v1 # save bits shifted out 2025 or t8, t8, v0 2026 srl t2, t2, t9 2027norm_noshift_s: 2028 move ta1, t1 # save unrounded exponent 2029 move ta2, t2 # save unrounded fraction 2030 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2031 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2032 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 2033 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2034 beq t0, zero, 5f # if sign is positive, truncate 2035 b 2f 20361: 2037 bne t0, zero, 5f # if sign is negative, truncate 20382: 2039 beq t8, zero, 5f # if exact, continue 2040 addu t2, t2, 1 # add rounding bit 2041 bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent? 2042 addu t1, t1, 1 # adjust exponent 2043 srl t2, t2, 1 # renormalize fraction 2044 b 5f 20453: 2046 li v0, GUARDBIT # load guard bit for rounding 2047 addu v0, v0, t8 # add remainder 2048 sltu v1, v0, t8 # compute carry out 2049 beq v1, zero, 4f # if no carry, continue 2050 addu t2, t2, 1 # add carry to result 2051 bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent? 2052 addu t1, t1, 1 # adjust exponent 2053 srl t2, t2, 1 # renormalize fraction 20544: 2055 bne v0, zero, 5f # if rounded remainder is zero 2056 and t2, t2, ~1 # clear LSB (round to nearest) 20575: 2058 bgt t1, SEXP_MAX, overflow_s # overflow? 2059 blt t1, SEXP_MIN, underflow_s # underflow? 2060 bne t8, zero, inexact_s # is result inexact? 2061 addu t1, t1, SEXP_BIAS # bias exponent 2062 and t2, t2, ~SIMPL_ONE # clear implied one bit 2063 b result_fs_s 2064 2065/* 2066 * Handle inexact exception. 2067 */ 2068inexact_s: 2069 addu t1, t1, SEXP_BIAS # bias exponent 2070 and t2, t2, ~SIMPL_ONE # clear implied one bit 2071inexact_nobias_s: 2072 jal _C_LABEL(set_fd_s) # save result 2073 or a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 2074 and v0, a2, MIPS_FPU_ENABLE_INEXACT 2075 bne v0, zero, fpe_trap 2076#ifdef SOFTFLOAT 2077 lw v0, _C_LABEL(curpcb) # get pcb of current process 2078 #nop 2079 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2080#else 2081 ctc1 a2, MIPS_FPU_CSR # save exceptions 2082#endif 2083 b done 2084 2085/* 2086 * Overflow will trap (if enabled), 2087 * or generate an inexact trap (if enabled), 2088 * or generate an infinity. 2089 */ 2090overflow_s: 2091 or a2, a2, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW 2092 and v0, a2, MIPS_FPU_ENABLE_OVERFLOW 2093 beq v0, zero, 1f 2094 subu t1, t1, 192 # bias exponent 2095 and t2, t2, ~SIMPL_ONE # clear implied one bit 2096 jal _C_LABEL(set_fd_s) # save result 2097 b fpe_trap 20981: 2099 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2100 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2101 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate) 2102 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity 2103 bne t0, zero, 3f 21041: 2105 li t1, SEXP_MAX # result is max finite 2106 li t2, 0x007fffff 2107 b inexact_s 21082: 2109 bne t0, zero, 1b 21103: 2111 li t1, SEXP_MAX + 1 # result is infinity 2112 move t2, zero 2113 b inexact_s 2114 2115/* 2116 * In this implementation, "tininess" is detected "after rounding" and 2117 * "loss of accuracy" is detected as "an inexact result". 2118 */ 2119underflow_s: 2120 and v0, a2, MIPS_FPU_ENABLE_UNDERFLOW 2121 beq v0, zero, 1f 2122/* 2123 * Underflow is enabled so compute the result and trap. 2124 */ 2125 addu t1, t1, 192 # bias exponent 2126 and t2, t2, ~SIMPL_ONE # clear implied one bit 2127 jal _C_LABEL(set_fd_s) # save result 2128 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2129 b fpe_trap 2130/* 2131 * Underflow is not enabled so compute the result, 2132 * signal inexact result (if it is) and trap (if enabled). 2133 */ 21341: 2135 move t1, ta1 # get unrounded exponent 2136 move t2, ta2 # get unrounded fraction 2137 li t9, SEXP_MIN # compute shift amount 2138 subu t9, t9, t1 # shift t2,t8 right by t9 2139 blt t9, SFRAC_BITS+2, 3f # shift all the bits out? 2140 move t1, zero # result is inexact zero 2141 move t2, zero 2142 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2143/* 2144 * Now round the zero result. 2145 * Only need to worry about rounding to +- infinity when the sign matches. 2146 */ 2147 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2148 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest 2149 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero 2150 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2151 beq t0, zero, inexact_nobias_s # if sign is positive, truncate 2152 b 2f 21531: 2154 bne t0, zero, inexact_nobias_s # if sign is negative, truncate 21552: 2156 addu t2, t2, 1 # add rounding bit 2157 b inexact_nobias_s 21583: 2159 li v1, 32 2160 subu v1, v1, t9 2161 sltu v0, zero, t8 # be sure to save any one bits 2162 sll t8, t2, v1 # save bits shifted out 2163 or t8, t8, v0 # include sticky bits 2164 srl t2, t2, t9 2165/* 2166 * Now round the denormalized result. 2167 */ 2168 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2169 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2170 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 2171 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2172 beq t0, zero, 5f # if sign is positive, truncate 2173 b 2f 21741: 2175 bne t0, zero, 5f # if sign is negative, truncate 21762: 2177 beq t8, zero, 5f # if exact, continue 2178 addu t2, t2, 1 # add rounding bit 2179 b 5f 21803: 2181 li v0, GUARDBIT # load guard bit for rounding 2182 addu v0, v0, t8 # add remainder 2183 sltu v1, v0, t8 # compute carry out 2184 beq v1, zero, 4f # if no carry, continue 2185 addu t2, t2, 1 # add carry to result 21864: 2187 bne v0, zero, 5f # if rounded remainder is zero 2188 and t2, t2, ~1 # clear LSB (round to nearest) 21895: 2190 move t1, zero # denorm or zero exponent 2191 jal _C_LABEL(set_fd_s) # save result 2192 beq t8, zero, done # check for exact result 2193 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2194 or a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 2195 and v0, a2, MIPS_FPU_ENABLE_INEXACT 2196 bne v0, zero, fpe_trap 2197#ifdef SOFTFLOAT 2198 lw v0, _C_LABEL(curpcb) # get pcb of current process 2199 #nop 2200 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2201#else 2202 ctc1 a2, MIPS_FPU_CSR # save exceptions 2203#endif 2204 b done 2205 2206/* 2207 * Determine the amount to shift the fraction in order to restore the 2208 * normalized position. After that, round and handle exceptions. 2209 */ 2210norm_d: 2211 move v0, t2 2212 move t9, zero # t9 = num of leading zeros 2213 bne t2, zero, 1f 2214 move v0, t3 2215 addu t9, 32 2216 bne t3, zero, 1f 2217 move v0, t8 2218 addu t9, 32 22191: 2220 srl v1, v0, 16 2221 bne v1, zero, 1f 2222 addu t9, 16 2223 sll v0, 16 22241: 2225 srl v1, v0, 24 2226 bne v1, zero, 1f 2227 addu t9, 8 2228 sll v0, 8 22291: 2230 srl v1, v0, 28 2231 bne v1, zero, 1f 2232 addu t9, 4 2233 sll v0, 4 22341: 2235 srl v1, v0, 30 2236 bne v1, zero, 1f 2237 addu t9, 2 2238 sll v0, 2 22391: 2240 srl v1, v0, 31 2241 bne v1, zero, 1f 2242 addu t9, 1 2243/* 2244 * Now shift t2,t3,t8 the correct number of bits. 2245 */ 22461: 2247 subu t9, t9, DLEAD_ZEROS # dont count leading zeros 2248 subu t1, t1, t9 # adjust the exponent 2249 beq t9, zero, norm_noshift_d 2250 li v1, 32 2251 blt t9, zero, 2f # if shift < 0, shift right 2252 blt t9, v1, 1f # shift by < 32? 2253 subu t9, t9, v1 # shift by >= 32 2254 subu v1, v1, t9 2255 sll t2, t3, t9 # shift left by t9 2256 srl v0, t8, v1 # save bits shifted out 2257 or t2, t2, v0 2258 sll t3, t8, t9 2259 move t8, zero 2260 b norm_noshift_d 22611: 2262 subu v1, v1, t9 2263 sll t2, t2, t9 # shift left by t9 2264 srl v0, t3, v1 # save bits shifted out 2265 or t2, t2, v0 2266 sll t3, t3, t9 2267 srl v0, t8, v1 # save bits shifted out 2268 or t3, t3, v0 2269 sll t8, t8, t9 2270 b norm_noshift_d 22712: 2272 negu t9 # shift right by t9 2273 subu v1, v1, t9 # (known to be < 32 bits) 2274 sll v0, t8, v1 # save bits shifted out 2275 sltu v0, zero, v0 # be sure to save any one bits 2276 srl t8, t8, t9 2277 or t8, t8, v0 2278 sll v0, t3, v1 # save bits shifted out 2279 or t8, t8, v0 2280 srl t3, t3, t9 2281 sll v0, t2, v1 # save bits shifted out 2282 or t3, t3, v0 2283 srl t2, t2, t9 2284norm_noshift_d: 2285 move ta1, t1 # save unrounded exponent 2286 move ta2, t2 # save unrounded fraction (MS) 2287 move ta3, t3 # save unrounded fraction (LS) 2288 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2289 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2290 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 2291 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2292 beq t0, zero, 5f # if sign is positive, truncate 2293 b 2f 22941: 2295 bne t0, zero, 5f # if sign is negative, truncate 22962: 2297 beq t8, zero, 5f # if exact, continue 2298 addu t3, t3, 1 # add rounding bit 2299 bne t3, zero, 5f # branch if no carry 2300 addu t2, t2, 1 # add carry 2301 bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent? 2302 addu t1, t1, 1 # adjust exponent 2303 srl t2, t2, 1 # renormalize fraction 2304 b 5f 23053: 2306 li v0, GUARDBIT # load guard bit for rounding 2307 addu v0, v0, t8 # add remainder 2308 sltu v1, v0, t8 # compute carry out 2309 beq v1, zero, 4f # branch if no carry 2310 addu t3, t3, 1 # add carry 2311 bne t3, zero, 4f # branch if no carry 2312 addu t2, t2, 1 # add carry to result 2313 bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent? 2314 addu t1, t1, 1 # adjust exponent 2315 srl t2, t2, 1 # renormalize fraction 23164: 2317 bne v0, zero, 5f # if rounded remainder is zero 2318 and t3, t3, ~1 # clear LSB (round to nearest) 23195: 2320 bgt t1, DEXP_MAX, overflow_d # overflow? 2321 blt t1, DEXP_MIN, underflow_d # underflow? 2322 bne t8, zero, inexact_d # is result inexact? 2323 addu t1, t1, DEXP_BIAS # bias exponent 2324 and t2, t2, ~DIMPL_ONE # clear implied one bit 2325 b result_fs_d 2326 2327/* 2328 * Handle inexact exception. 2329 */ 2330inexact_d: 2331 addu t1, t1, DEXP_BIAS # bias exponent 2332 and t2, t2, ~DIMPL_ONE # clear implied one bit 2333inexact_nobias_d: 2334 jal _C_LABEL(set_fd_d) # save result 2335 or a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 2336 and v0, a2, MIPS_FPU_ENABLE_INEXACT 2337 bne v0, zero, fpe_trap 2338#ifdef SOFTFLOAT 2339 lw v0, _C_LABEL(curpcb) # get pcb of current process 2340 #nop 2341 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2342#else 2343 ctc1 a2, MIPS_FPU_CSR # save exceptions 2344#endif 2345 b done 2346 2347/* 2348 * Overflow will trap (if enabled), 2349 * or generate an inexact trap (if enabled), 2350 * or generate an infinity. 2351 */ 2352overflow_d: 2353 or a2, a2, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW 2354 and v0, a2, MIPS_FPU_ENABLE_OVERFLOW 2355 beq v0, zero, 1f 2356 subu t1, t1, 1536 # bias exponent 2357 and t2, t2, ~DIMPL_ONE # clear implied one bit 2358 jal _C_LABEL(set_fd_d) # save result 2359 b fpe_trap 23601: 2361 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2362 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2363 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate) 2364 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity 2365 bne t0, zero, 3f 23661: 2367 li t1, DEXP_MAX # result is max finite 2368 li t2, 0x000fffff 2369 li t3, 0xffffffff 2370 b inexact_d 23712: 2372 bne t0, zero, 1b 23733: 2374 li t1, DEXP_MAX + 1 # result is infinity 2375 move t2, zero 2376 move t3, zero 2377 b inexact_d 2378 2379/* 2380 * In this implementation, "tininess" is detected "after rounding" and 2381 * "loss of accuracy" is detected as "an inexact result". 2382 */ 2383underflow_d: 2384 and v0, a2, MIPS_FPU_ENABLE_UNDERFLOW 2385 beq v0, zero, 1f 2386/* 2387 * Underflow is enabled so compute the result and trap. 2388 */ 2389 addu t1, t1, 1536 # bias exponent 2390 and t2, t2, ~DIMPL_ONE # clear implied one bit 2391 jal _C_LABEL(set_fd_d) # save result 2392 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2393 b fpe_trap 2394/* 2395 * Underflow is not enabled so compute the result, 2396 * signal inexact result (if it is) and trap (if enabled). 2397 */ 23981: 2399 move t1, ta1 # get unrounded exponent 2400 move t2, ta2 # get unrounded fraction (MS) 2401 move t3, ta3 # get unrounded fraction (LS) 2402 li t9, DEXP_MIN # compute shift amount 2403 subu t9, t9, t1 # shift t2,t8 right by t9 2404 blt t9, DFRAC_BITS+2, 3f # shift all the bits out? 2405 move t1, zero # result is inexact zero 2406 move t2, zero 2407 move t3, zero 2408 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2409/* 2410 * Now round the zero result. 2411 * Only need to worry about rounding to +- infinity when the sign matches. 2412 */ 2413 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2414 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_d # round to nearest 2415 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d # round to zero 2416 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2417 beq t0, zero, inexact_nobias_d # if sign is positive, truncate 2418 b 2f 24191: 2420 bne t0, zero, inexact_nobias_d # if sign is negative, truncate 24212: 2422 addu t3, t3, 1 # add rounding bit 2423 b inexact_nobias_d 24243: 2425 li v1, 32 2426 blt t9, v1, 1f # shift by < 32? 2427 subu t9, t9, v1 # shift right by >= 32 2428 subu v1, v1, t9 2429 sltu v0, zero, t8 # be sure to save any one bits 2430 sll t8, t2, v1 # save bits shifted out 2431 or t8, t8, v0 # include sticky bits 2432 srl t3, t2, t9 2433 move t2, zero 2434 b 2f 24351: 2436 subu v1, v1, t9 # shift right by t9 2437 sltu v0, zero, t8 # be sure to save any one bits 2438 sll t8, t3, v1 # save bits shifted out 2439 or t8, t8, v0 # include sticky bits 2440 srl t3, t3, t9 2441 sll v0, t2, v1 # save bits shifted out 2442 or t3, t3, v0 2443 srl t2, t2, t9 2444/* 2445 * Now round the denormalized result. 2446 */ 24472: 2448 and v0, a2, MIPS_FPU_ROUNDING_BITS # get rounding mode 2449 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest 2450 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate) 2451 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity 2452 beq t0, zero, 5f # if sign is positive, truncate 2453 b 2f 24541: 2455 bne t0, zero, 5f # if sign is negative, truncate 24562: 2457 beq t8, zero, 5f # if exact, continue 2458 addu t3, t3, 1 # add rounding bit 2459 bne t3, zero, 5f # if no carry, continue 2460 addu t2, t2, 1 # add carry 2461 b 5f 24623: 2463 li v0, GUARDBIT # load guard bit for rounding 2464 addu v0, v0, t8 # add remainder 2465 sltu v1, v0, t8 # compute carry out 2466 beq v1, zero, 4f # if no carry, continue 2467 addu t3, t3, 1 # add rounding bit 2468 bne t3, zero, 4f # if no carry, continue 2469 addu t2, t2, 1 # add carry 24704: 2471 bne v0, zero, 5f # if rounded remainder is zero 2472 and t3, t3, ~1 # clear LSB (round to nearest) 24735: 2474 move t1, zero # denorm or zero exponent 2475 jal _C_LABEL(set_fd_d) # save result 2476 beq t8, zero, done # check for exact result 2477 or a2, a2, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW 2478 or a2, a2, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT 2479 and v0, a2, MIPS_FPU_ENABLE_INEXACT 2480 bne v0, zero, fpe_trap 2481#ifdef SOFTFLOAT 2482 lw v0, _C_LABEL(curpcb) # get pcb of current process 2483 #nop 2484 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2485#else 2486 ctc1 a2, MIPS_FPU_CSR # save exceptions 2487#endif 2488 b done 2489 2490/* 2491 * Signal an invalid operation if the trap is enabled; otherwise, 2492 * the result is a quiet NAN. 2493 */ 2494invalid_s: # trap invalid operation 2495 or a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 2496 and v0, a2, MIPS_FPU_ENABLE_INVALID 2497 bne v0, zero, fpe_trap 2498#ifdef SOFTFLOAT 2499 lw v0, _C_LABEL(curpcb) # get pcb of current process 2500 #nop 2501 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2502#else 2503 ctc1 a2, MIPS_FPU_CSR # save exceptions 2504#endif 2505 move t0, zero # result is a quiet NAN 2506 li t1, SEXP_INF 2507 li t2, SQUIET_NAN 2508 jal _C_LABEL(set_fd_s) # save result (in t0,t1,t2) 2509 b done 2510 2511/* 2512 * Signal an invalid operation if the trap is enabled; otherwise, 2513 * the result is a quiet NAN. 2514 */ 2515invalid_d: # trap invalid operation 2516 or a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 2517 and v0, a2, MIPS_FPU_ENABLE_INVALID 2518 bne v0, zero, fpe_trap 2519#ifdef SOFTFLOAT 2520 lw v0, _C_LABEL(curpcb) # get pcb of current process 2521 #nop 2522 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2523#else 2524 ctc1 a2, MIPS_FPU_CSR # save exceptions 2525#endif 2526 move t0, zero # result is a quiet NAN 2527 li t1, DEXP_INF 2528 li t2, DQUIET_NAN0 2529 li t3, DQUIET_NAN1 2530 jal _C_LABEL(set_fd_d) # save result (in t0,t1,t2,t3) 2531 b done 2532 2533/* 2534 * Signal an invalid operation if the trap is enabled; otherwise, 2535 * the result is INT_MAX or INT_MIN. 2536 */ 2537invalid_w: # trap invalid operation 2538 or a2, a2, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID 2539 and v0, a2, MIPS_FPU_ENABLE_INVALID 2540 bne v0, zero, fpe_trap 2541#ifdef SOFTFLOAT 2542 lw v0, _C_LABEL(curpcb) # get pcb of current process 2543 #nop 2544 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2545#else 2546 ctc1 a2, MIPS_FPU_CSR # save exceptions 2547#endif 2548 bne t0, zero, 1f 2549 li t2, INT_MAX # result is INT_MAX 2550 b result_fs_w 25511: 2552 li t2, INT_MIN # result is INT_MIN 2553 b result_fs_w 2554 2555/* 2556 * Trap if the hardware should have handled this case. 2557 */ 2558fpe_trap: 2559#ifdef SOFTFLOAT 2560 lw v0, _C_LABEL(curpcb) # get pcb of current process 2561 #nop 2562 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2563#else 2564 /* 2565 * ctc1 with fpe bits set causes FPE in kernel mode panic on 5231. 2566 */ 2567 sw a2, CALLFRAME_SIZ + 12(sp) 2568 lw a0, _C_LABEL(fpcurproc) 2569 jal _C_LABEL(savefpregs) # on RM5231 2570 2571 lw a2, CALLFRAME_SIZ + 12(sp) 2572 2573 lw v0, _C_LABEL(curpcb) # get pcb of current process 2574 #nop 2575 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2576#endif 2577 lw a1, CALLFRAME_SIZ + 16(sp) # frame 2578 lw a2, CALLFRAME_SIZ + 8(sp) # cause 2579 lw ra, CALLFRAME_RA(sp) 2580 addu sp, sp, CALLFRAME_SIZ 2581 j _C_LABEL(fpemul_sigfpe) 2582 2583/* 2584 * Send an illegal instruction signal to the current process. 2585 */ 2586ill: 2587#ifdef SOFTFLOAT 2588 lw v0, _C_LABEL(curpcb) # get pcb of current process 2589 #nop 2590 sw a2, U_PCB_FPREGS+FRAME_FSR(v0) 2591#else 2592 ctc1 a2, MIPS_FPU_CSR # save exceptions 2593#endif 2594 lw a1, CALLFRAME_SIZ + 16(sp) # frame 2595 lw a2, CALLFRAME_SIZ + 8(sp) # cause 2596 lw ra, CALLFRAME_RA(sp) 2597 addu sp, sp, CALLFRAME_SIZ 2598 j _C_LABEL(fpemul_sigill) 2599 2600result_ft_s: 2601 move t0, ta0 # result is FT 2602 move t1, ta1 2603 move t2, ta2 2604result_fs_s: # result is FS 2605 jal _C_LABEL(set_fd_s) # save result (in t0,t1,t2) 2606 b done 2607 2608result_fs_w: 2609 jal _C_LABEL(set_fd_word) # save result (in t2) 2610 b done 2611 2612result_ft_d: 2613 move t0, ta0 # result is FT 2614 move t1, ta1 2615 move t2, ta2 2616 move t3, ta3 2617result_fs_d: # result is FS 2618 jal _C_LABEL(set_fd_d) # save result (in t0,t1,t2,t3) 2619 2620done: 2621/* 2622 * Succeeded to emulate instruction with no error 2623 * so compute the next PC. 2624 */ 2625 lw t0, CALLFRAME_SIZ + 8(sp) 2626 REG_PROLOGUE 2627 REG_L v0, FRAME_EPC(a1) 2628 REG_EPILOGUE 2629 bgez t0, 1f # Check the branch delay bit. 2630/* 2631 * The instruction is in the branch delay slot so the branch will have to 2632 * be emulated to get the resulting PC. 2633 */ 2634 sw a1, CALLFRAME_SIZ + 4(sp) 2635 move a0, a1 # 1st arg is p. to trapframe 2636 move a1, v0 # 2nd arg is instruction PC 2637 # 3rd arg is FP CSR 2638 move a3, zero # 4th arg is FALSE 2639 jal _C_LABEL(MachEmulateBranch) # compute PC after branch 2640 2641 lw a1, CALLFRAME_SIZ + 4(sp) 2642 b 2f 2643/* 2644 * This is not in the branch delay slot so calculate the resulting 2645 * PC (epc + 4) into v0. 2646 */ 26471: 2648 addiu v0, v0, 4 # v0 = next pc 26492: 2650 REG_PROLOGUE 2651 REG_S v0, FRAME_EPC(a1) # save new pc 2652 REG_EPILOGUE 2653 2654 lw ra, CALLFRAME_RA(sp) 2655 addu sp, sp, CALLFRAME_SIZ 2656 j ra 2657END(MachEmulateFP) 2658 2659/*---------------------------------------------------------------------------- 2660 * get_fs_int -- 2661 * 2662 * Read (integer) the FS register (bits 15-11). 2663 * This is an internal routine used by MachEmulateFP only. 2664 * 2665 * Results: 2666 * t0 contains the sign 2667 * t2 contains the fraction 2668 * 2669 *---------------------------------------------------------------------------- 2670 */ 2671LEAF(get_fs_int) 2672#ifdef SOFTFLOAT 2673 srl t2, a0, 11-2 2674 lw t0, _C_LABEL(curpcb) # get pcb of current process 2675 andi t2, t2, 0x0078 # Even regs only 2676 addu t0, t0, t2 2677 2678 lw t2, U_PCB_FPREGS+FRAME_FP0(t0) 2679 2680 srl t0, t2, 31 # init the sign bit 2681 bge t2, zero, 1f 2682 negu t2 26831: 2684 j ra 2685#else 2686 srl a3, a0, 12 - 2 # get FS field (even regs only) 2687 and a3, a3, 0xF << 2 # mask FS field 2688 lw a3, get_fs_int_tbl(a3) # switch on register number 2689 j a3 2690 2691 .rdata 2692get_fs_int_tbl: 2693 .word get_fs_int_f0 2694 .word get_fs_int_f2 2695 .word get_fs_int_f4 2696 .word get_fs_int_f6 2697 .word get_fs_int_f8 2698 .word get_fs_int_f10 2699 .word get_fs_int_f12 2700 .word get_fs_int_f14 2701 .word get_fs_int_f16 2702 .word get_fs_int_f18 2703 .word get_fs_int_f20 2704 .word get_fs_int_f22 2705 .word get_fs_int_f24 2706 .word get_fs_int_f26 2707 .word get_fs_int_f28 2708 .word get_fs_int_f30 2709 .text 2710 2711get_fs_int_f0: 2712 mfc1 t2, $f0 2713 b get_fs_int_done 2714get_fs_int_f2: 2715 mfc1 t2, $f2 2716 b get_fs_int_done 2717get_fs_int_f4: 2718 mfc1 t2, $f4 2719 b get_fs_int_done 2720get_fs_int_f6: 2721 mfc1 t2, $f6 2722 b get_fs_int_done 2723get_fs_int_f8: 2724 mfc1 t2, $f8 2725 b get_fs_int_done 2726get_fs_int_f10: 2727 mfc1 t2, $f10 2728 b get_fs_int_done 2729get_fs_int_f12: 2730 mfc1 t2, $f12 2731 b get_fs_int_done 2732get_fs_int_f14: 2733 mfc1 t2, $f14 2734 b get_fs_int_done 2735get_fs_int_f16: 2736 mfc1 t2, $f16 2737 b get_fs_int_done 2738get_fs_int_f18: 2739 mfc1 t2, $f18 2740 b get_fs_int_done 2741get_fs_int_f20: 2742 mfc1 t2, $f20 2743 b get_fs_int_done 2744get_fs_int_f22: 2745 mfc1 t2, $f22 2746 b get_fs_int_done 2747get_fs_int_f24: 2748 mfc1 t2, $f24 2749 b get_fs_int_done 2750get_fs_int_f26: 2751 mfc1 t2, $f26 2752 b get_fs_int_done 2753get_fs_int_f28: 2754 mfc1 t2, $f28 2755 b get_fs_int_done 2756get_fs_int_f30: 2757 mfc1 t2, $f30 2758get_fs_int_done: 2759 srl t0, t2, 31 # init the sign bit 2760 bge t2, zero, 1f 2761 negu t2 27621: 2763 j ra 2764#endif 2765END(get_fs_int) 2766 2767/*---------------------------------------------------------------------------- 2768 * get_ft_fs_s -- 2769 * 2770 * Read (single precision) the FT register (bits 20-16) and 2771 * the FS register (bits 15-11) and break up into fields. 2772 * This is an internal routine used by MachEmulateFP only. 2773 * 2774 * Results: 2775 * t0 contains the FS sign 2776 * t1 contains the FS (biased) exponent 2777 * t2 contains the FS fraction 2778 * ta0 contains the FT sign 2779 * ta1 contains the FT (biased) exponent 2780 * ta2 contains the FT fraction 2781 * 2782 *---------------------------------------------------------------------------- 2783 */ 2784LEAF(get_ft_fs_s) 2785#ifdef SOFTFLOAT 2786 srl ta0, a0, 16-2 2787 lw ta1, _C_LABEL(curpcb) # get pcb of current process 2788 andi ta0, ta0, 0x0078 # Even regs only 2789 addu ta1, ta1, ta0 2790 2791 lw ta0, U_PCB_FPREGS+FRAME_FP0(ta1) 2792 2793 srl ta1, ta0, 23 # get exponent 2794 and ta1, ta1, 0xFF 2795 and ta2, ta0, 0x7FFFFF # get fraction 2796 srl ta0, ta0, 31 # get sign 2797 bne ta1, SEXP_INF, 1f # is it a signaling NAN? 2798 and v0, ta2, SSIGNAL_NAN 2799 bne v0, zero, invalid_s 28001: 2801 /* fall through to get FS */ 2802#else 2803 srl a3, a0, 17 - 2 # get FT field (even regs only) 2804 and a3, a3, 0xF << 2 # mask FT field 2805 lw a3, get_ft_s_tbl(a3) # switch on register number 2806 j a3 2807 2808 .rdata 2809get_ft_s_tbl: 2810 .word get_ft_s_f0 2811 .word get_ft_s_f2 2812 .word get_ft_s_f4 2813 .word get_ft_s_f6 2814 .word get_ft_s_f8 2815 .word get_ft_s_f10 2816 .word get_ft_s_f12 2817 .word get_ft_s_f14 2818 .word get_ft_s_f16 2819 .word get_ft_s_f18 2820 .word get_ft_s_f20 2821 .word get_ft_s_f22 2822 .word get_ft_s_f24 2823 .word get_ft_s_f26 2824 .word get_ft_s_f28 2825 .word get_ft_s_f30 2826 .text 2827 2828get_ft_s_f0: 2829 mfc1 ta0, $f0 2830 b get_ft_s_done 2831get_ft_s_f2: 2832 mfc1 ta0, $f2 2833 b get_ft_s_done 2834get_ft_s_f4: 2835 mfc1 ta0, $f4 2836 b get_ft_s_done 2837get_ft_s_f6: 2838 mfc1 ta0, $f6 2839 b get_ft_s_done 2840get_ft_s_f8: 2841 mfc1 ta0, $f8 2842 b get_ft_s_done 2843get_ft_s_f10: 2844 mfc1 ta0, $f10 2845 b get_ft_s_done 2846get_ft_s_f12: 2847 mfc1 ta0, $f12 2848 b get_ft_s_done 2849get_ft_s_f14: 2850 mfc1 ta0, $f14 2851 b get_ft_s_done 2852get_ft_s_f16: 2853 mfc1 ta0, $f16 2854 b get_ft_s_done 2855get_ft_s_f18: 2856 mfc1 ta0, $f18 2857 b get_ft_s_done 2858get_ft_s_f20: 2859 mfc1 ta0, $f20 2860 b get_ft_s_done 2861get_ft_s_f22: 2862 mfc1 ta0, $f22 2863 b get_ft_s_done 2864get_ft_s_f24: 2865 mfc1 ta0, $f24 2866 b get_ft_s_done 2867get_ft_s_f26: 2868 mfc1 ta0, $f26 2869 b get_ft_s_done 2870get_ft_s_f28: 2871 mfc1 ta0, $f28 2872 b get_ft_s_done 2873get_ft_s_f30: 2874 mfc1 ta0, $f30 2875get_ft_s_done: 2876 srl ta1, ta0, 23 # get exponent 2877 and ta1, ta1, 0xFF 2878 and ta2, ta0, 0x7FFFFF # get fraction 2879 srl ta0, ta0, 31 # get sign 2880 bne ta1, SEXP_INF, 1f # is it a signaling NAN? 2881 and v0, ta2, SSIGNAL_NAN 2882 bne v0, zero, invalid_s 28831: 2884 /* fall through to get FS */ 2885#endif 2886 2887/*---------------------------------------------------------------------------- 2888 * get_fs_s -- 2889 * 2890 * Read (single precision) the FS register (bits 15-11) and 2891 * break up into fields. 2892 * This is an internal routine used by MachEmulateFP only. 2893 * 2894 * Results: 2895 * t0 contains the sign 2896 * t1 contains the (biased) exponent 2897 * t2 contains the fraction 2898 * 2899 *---------------------------------------------------------------------------- 2900 */ 2901XLEAF(get_fs_s) 2902#ifdef SOFTFLOAT 2903 srl t0, a0, 11-2 2904 lw t1, _C_LABEL(curpcb) # get pcb of current process 2905 andi t0, t0, 0x0078 # Even regs only 2906 addu t1, t1, t0 2907 2908 lw t0, U_PCB_FPREGS+FRAME_FP0(t1) 2909 2910 srl t1, t0, 23 # get exponent 2911 and t1, t1, 0xFF 2912 and t2, t0, 0x7FFFFF # get fraction 2913 srl t0, t0, 31 # get sign 2914 bne t1, SEXP_INF, 1f # is it a signaling NAN? 2915 and v0, t2, SSIGNAL_NAN 2916 bne v0, zero, invalid_s 29171: 2918 j ra 2919#else 2920 srl a3, a0, 12 - 2 # get FS field (even regs only) 2921 and a3, a3, 0xF << 2 # mask FS field 2922 lw a3, get_fs_s_tbl(a3) # switch on register number 2923 j a3 2924 2925 .rdata 2926get_fs_s_tbl: 2927 .word get_fs_s_f0 2928 .word get_fs_s_f2 2929 .word get_fs_s_f4 2930 .word get_fs_s_f6 2931 .word get_fs_s_f8 2932 .word get_fs_s_f10 2933 .word get_fs_s_f12 2934 .word get_fs_s_f14 2935 .word get_fs_s_f16 2936 .word get_fs_s_f18 2937 .word get_fs_s_f20 2938 .word get_fs_s_f22 2939 .word get_fs_s_f24 2940 .word get_fs_s_f26 2941 .word get_fs_s_f28 2942 .word get_fs_s_f30 2943 .text 2944 2945get_fs_s_f0: 2946 mfc1 t0, $f0 2947 b get_fs_s_done 2948get_fs_s_f2: 2949 mfc1 t0, $f2 2950 b get_fs_s_done 2951get_fs_s_f4: 2952 mfc1 t0, $f4 2953 b get_fs_s_done 2954get_fs_s_f6: 2955 mfc1 t0, $f6 2956 b get_fs_s_done 2957get_fs_s_f8: 2958 mfc1 t0, $f8 2959 b get_fs_s_done 2960get_fs_s_f10: 2961 mfc1 t0, $f10 2962 b get_fs_s_done 2963get_fs_s_f12: 2964 mfc1 t0, $f12 2965 b get_fs_s_done 2966get_fs_s_f14: 2967 mfc1 t0, $f14 2968 b get_fs_s_done 2969get_fs_s_f16: 2970 mfc1 t0, $f16 2971 b get_fs_s_done 2972get_fs_s_f18: 2973 mfc1 t0, $f18 2974 b get_fs_s_done 2975get_fs_s_f20: 2976 mfc1 t0, $f20 2977 b get_fs_s_done 2978get_fs_s_f22: 2979 mfc1 t0, $f22 2980 b get_fs_s_done 2981get_fs_s_f24: 2982 mfc1 t0, $f24 2983 b get_fs_s_done 2984get_fs_s_f26: 2985 mfc1 t0, $f26 2986 b get_fs_s_done 2987get_fs_s_f28: 2988 mfc1 t0, $f28 2989 b get_fs_s_done 2990get_fs_s_f30: 2991 mfc1 t0, $f30 2992get_fs_s_done: 2993 srl t1, t0, 23 # get exponent 2994 and t1, t1, 0xFF 2995 and t2, t0, 0x7FFFFF # get fraction 2996 srl t0, t0, 31 # get sign 2997 bne t1, SEXP_INF, 1f # is it a signaling NAN? 2998 and v0, t2, SSIGNAL_NAN 2999 bne v0, zero, invalid_s 30001: 3001 j ra 3002#endif 3003END(get_ft_fs_s) 3004 3005/*---------------------------------------------------------------------------- 3006 * get_ft_fs_d -- 3007 * 3008 * Read (double precision) the FT register (bits 20-16) and 3009 * the FS register (bits 15-11) and break up into fields. 3010 * This is an internal routine used by MachEmulateFP only. 3011 * 3012 * Results: 3013 * t0 contains the FS sign 3014 * t1 contains the FS (biased) exponent 3015 * t2 contains the FS fraction 3016 * t3 contains the FS remaining fraction 3017 * ta0 contains the FT sign 3018 * ta1 contains the FT (biased) exponent 3019 * ta2 contains the FT fraction 3020 * ta3 contains the FT remaining fraction 3021 * 3022 *---------------------------------------------------------------------------- 3023 */ 3024LEAF(get_ft_fs_d) 3025#ifdef SOFTFLOAT 3026 srl ta3, a0, 16-2 3027 lw ta0, _C_LABEL(curpcb) # get pcb of current process 3028 andi ta3, ta3, 0x0078 # Even regs only 3029 addu ta0, ta0, ta3 3030 3031 lw ta3, U_PCB_FPREGS+FRAME_FP0(ta0) 3032 lw ta0, U_PCB_FPREGS+FRAME_FP0+4(ta0) 3033 3034 srl ta1, ta0, 20 # get exponent 3035 and ta1, ta1, 0x7FF 3036 and ta2, ta0, 0xFFFFF # get fraction 3037 srl ta0, ta0, 31 # get sign 3038 bne ta1, DEXP_INF, 1f # is it a signaling NAN? 3039 and v0, ta2, DSIGNAL_NAN 3040 bne v0, zero, invalid_d 30411: 3042 /* fall through to get FS */ 3043#else 3044 srl a3, a0, 17 - 2 # get FT field (even regs only) 3045 and a3, a3, 0xF << 2 # mask FT field 3046 lw a3, get_ft_d_tbl(a3) # switch on register number 3047 j a3 3048 3049 .rdata 3050get_ft_d_tbl: 3051 .word get_ft_d_f0 3052 .word get_ft_d_f2 3053 .word get_ft_d_f4 3054 .word get_ft_d_f6 3055 .word get_ft_d_f8 3056 .word get_ft_d_f10 3057 .word get_ft_d_f12 3058 .word get_ft_d_f14 3059 .word get_ft_d_f16 3060 .word get_ft_d_f18 3061 .word get_ft_d_f20 3062 .word get_ft_d_f22 3063 .word get_ft_d_f24 3064 .word get_ft_d_f26 3065 .word get_ft_d_f28 3066 .word get_ft_d_f30 3067 .text 3068 3069get_ft_d_f0: 3070 mfc1 ta3, $f0 3071 mfc1 ta0, $f1 3072 b get_ft_d_done 3073get_ft_d_f2: 3074 mfc1 ta3, $f2 3075 mfc1 ta0, $f3 3076 b get_ft_d_done 3077get_ft_d_f4: 3078 mfc1 ta3, $f4 3079 mfc1 ta0, $f5 3080 b get_ft_d_done 3081get_ft_d_f6: 3082 mfc1 ta3, $f6 3083 mfc1 ta0, $f7 3084 b get_ft_d_done 3085get_ft_d_f8: 3086 mfc1 ta3, $f8 3087 mfc1 ta0, $f9 3088 b get_ft_d_done 3089get_ft_d_f10: 3090 mfc1 ta3, $f10 3091 mfc1 ta0, $f11 3092 b get_ft_d_done 3093get_ft_d_f12: 3094 mfc1 ta3, $f12 3095 mfc1 ta0, $f13 3096 b get_ft_d_done 3097get_ft_d_f14: 3098 mfc1 ta3, $f14 3099 mfc1 ta0, $f15 3100 b get_ft_d_done 3101get_ft_d_f16: 3102 mfc1 ta3, $f16 3103 mfc1 ta0, $f17 3104 b get_ft_d_done 3105get_ft_d_f18: 3106 mfc1 ta3, $f18 3107 mfc1 ta0, $f19 3108 b get_ft_d_done 3109get_ft_d_f20: 3110 mfc1 ta3, $f20 3111 mfc1 ta0, $f21 3112 b get_ft_d_done 3113get_ft_d_f22: 3114 mfc1 ta3, $f22 3115 mfc1 ta0, $f23 3116 b get_ft_d_done 3117get_ft_d_f24: 3118 mfc1 ta3, $f24 3119 mfc1 ta0, $f25 3120 b get_ft_d_done 3121get_ft_d_f26: 3122 mfc1 ta3, $f26 3123 mfc1 ta0, $f27 3124 b get_ft_d_done 3125get_ft_d_f28: 3126 mfc1 ta3, $f28 3127 mfc1 ta0, $f29 3128 b get_ft_d_done 3129get_ft_d_f30: 3130 mfc1 ta3, $f30 3131 mfc1 ta0, $f31 3132get_ft_d_done: 3133 srl ta1, ta0, 20 # get exponent 3134 and ta1, ta1, 0x7FF 3135 and ta2, ta0, 0xFFFFF # get fraction 3136 srl ta0, ta0, 31 # get sign 3137 bne ta1, DEXP_INF, 1f # is it a signaling NAN? 3138 and v0, ta2, DSIGNAL_NAN 3139 bne v0, zero, invalid_d 31401: 3141 /* fall through to get FS */ 3142#endif 3143 3144/*---------------------------------------------------------------------------- 3145 * get_fs_d -- 3146 * 3147 * Read (double precision) the FS register (bits 15-11) and 3148 * break up into fields. 3149 * This is an internal routine used by MachEmulateFP only. 3150 * 3151 * Results: 3152 * t0 contains the sign 3153 * t1 contains the (biased) exponent 3154 * t2 contains the fraction 3155 * t3 contains the remaining fraction 3156 * 3157 *---------------------------------------------------------------------------- 3158 */ 3159XLEAF(get_fs_d) 3160#ifdef SOFTFLOAT 3161 srl t3, a0, 11-2 3162 lw t0, _C_LABEL(curpcb) # get pcb of current process 3163 andi t3, t3, 0x0078 # Even regs only 3164 addu t0, t0, t3 3165 3166 lw t3, U_PCB_FPREGS+FRAME_FP0(t0) 3167 lw t0, U_PCB_FPREGS+FRAME_FP0+4(t0) 3168 3169 srl t1, t0, 20 # get exponent 3170 and t1, t1, 0x7FF 3171 and t2, t0, 0xFFFFF # get fraction 3172 srl t0, t0, 31 # get sign 3173 bne t1, DEXP_INF, 1f # is it a signaling NAN? 3174 and v0, t2, DSIGNAL_NAN 3175 bne v0, zero, invalid_d 31761: 3177 j ra 3178#else 3179 srl a3, a0, 12 - 2 # get FS field (even regs only) 3180 and a3, a3, 0xF << 2 # mask FS field 3181 lw a3, get_fs_d_tbl(a3) # switch on register number 3182 j a3 3183 3184 .rdata 3185get_fs_d_tbl: 3186 .word get_fs_d_f0 3187 .word get_fs_d_f2 3188 .word get_fs_d_f4 3189 .word get_fs_d_f6 3190 .word get_fs_d_f8 3191 .word get_fs_d_f10 3192 .word get_fs_d_f12 3193 .word get_fs_d_f14 3194 .word get_fs_d_f16 3195 .word get_fs_d_f18 3196 .word get_fs_d_f20 3197 .word get_fs_d_f22 3198 .word get_fs_d_f24 3199 .word get_fs_d_f26 3200 .word get_fs_d_f28 3201 .word get_fs_d_f30 3202 .text 3203 3204get_fs_d_f0: 3205 mfc1 t3, $f0 3206 mfc1 t0, $f1 3207 b get_fs_d_done 3208get_fs_d_f2: 3209 mfc1 t3, $f2 3210 mfc1 t0, $f3 3211 b get_fs_d_done 3212get_fs_d_f4: 3213 mfc1 t3, $f4 3214 mfc1 t0, $f5 3215 b get_fs_d_done 3216get_fs_d_f6: 3217 mfc1 t3, $f6 3218 mfc1 t0, $f7 3219 b get_fs_d_done 3220get_fs_d_f8: 3221 mfc1 t3, $f8 3222 mfc1 t0, $f9 3223 b get_fs_d_done 3224get_fs_d_f10: 3225 mfc1 t3, $f10 3226 mfc1 t0, $f11 3227 b get_fs_d_done 3228get_fs_d_f12: 3229 mfc1 t3, $f12 3230 mfc1 t0, $f13 3231 b get_fs_d_done 3232get_fs_d_f14: 3233 mfc1 t3, $f14 3234 mfc1 t0, $f15 3235 b get_fs_d_done 3236get_fs_d_f16: 3237 mfc1 t3, $f16 3238 mfc1 t0, $f17 3239 b get_fs_d_done 3240get_fs_d_f18: 3241 mfc1 t3, $f18 3242 mfc1 t0, $f19 3243 b get_fs_d_done 3244get_fs_d_f20: 3245 mfc1 t3, $f20 3246 mfc1 t0, $f21 3247 b get_fs_d_done 3248get_fs_d_f22: 3249 mfc1 t3, $f22 3250 mfc1 t0, $f23 3251 b get_fs_d_done 3252get_fs_d_f24: 3253 mfc1 t3, $f24 3254 mfc1 t0, $f25 3255 b get_fs_d_done 3256get_fs_d_f26: 3257 mfc1 t3, $f26 3258 mfc1 t0, $f27 3259 b get_fs_d_done 3260get_fs_d_f28: 3261 mfc1 t3, $f28 3262 mfc1 t0, $f29 3263 b get_fs_d_done 3264get_fs_d_f30: 3265 mfc1 t3, $f30 3266 mfc1 t0, $f31 3267get_fs_d_done: 3268 srl t1, t0, 20 # get exponent 3269 and t1, t1, 0x7FF 3270 and t2, t0, 0xFFFFF # get fraction 3271 srl t0, t0, 31 # get sign 3272 bne t1, DEXP_INF, 1f # is it a signaling NAN? 3273 and v0, t2, DSIGNAL_NAN 3274 bne v0, zero, invalid_d 32751: 3276 j ra 3277#endif 3278END(get_ft_fs_d) 3279 3280/*---------------------------------------------------------------------------- 3281 * get_cmp_s -- 3282 * 3283 * Read (single precision) the FS register (bits 15-11) and 3284 * the FT register (bits 20-16) and break up into fields. 3285 * This is an internal routine used by MachEmulateFP only. 3286 * 3287 * Results: 3288 * t0 contains the sign 3289 * t1 contains the (biased) exponent 3290 * t2 contains the fraction 3291 * ta0 contains the sign 3292 * ta1 contains the (biased) exponent 3293 * ta2 contains the fraction 3294 * 3295 *---------------------------------------------------------------------------- 3296 */ 3297LEAF(get_cmp_s) 3298#ifdef SOFTFLOAT 3299 srl t1, a0, 11-2 3300 lw ta2, _C_LABEL(curpcb) # get pcb of current process 3301 andi t1, t1, 0x0078 # Even regs only 3302 addu t0, ta2, t1 3303 3304 lw t0, U_PCB_FPREGS+FRAME_FP0(t0) 3305 3306 srl t1, t0, 23 # get exponent 3307 and t1, t1, 0xFF 3308 and t2, t0, 0x7FFFFF # get fraction 3309 srl t0, t0, 31 # get sign 3310 3311 srl ta0, a0, 16-2 3312 andi ta0, ta0, 0x0078 # Even regs only 3313 addu ta2, ta2, ta0 3314 3315 lw ta0, U_PCB_FPREGS+FRAME_FP0(ta2) 3316 3317 srl ta1, ta0, 23 # get exponent 3318 and ta1, ta1, 0xFF 3319 and ta2, ta0, 0x7FFFFF # get fraction 3320 srl ta0, ta0, 31 # get sign 3321 j ra 3322#else 3323 srl a3, a0, 12 - 2 # get FS field (even regs only) 3324 and a3, a3, 0xF << 2 # mask FS field 3325 lw a3, cmp_fs_s_tbl(a3) # switch on register number 3326 j a3 3327 3328 .rdata 3329cmp_fs_s_tbl: 3330 .word cmp_fs_s_f0 3331 .word cmp_fs_s_f2 3332 .word cmp_fs_s_f4 3333 .word cmp_fs_s_f6 3334 .word cmp_fs_s_f8 3335 .word cmp_fs_s_f10 3336 .word cmp_fs_s_f12 3337 .word cmp_fs_s_f14 3338 .word cmp_fs_s_f16 3339 .word cmp_fs_s_f18 3340 .word cmp_fs_s_f20 3341 .word cmp_fs_s_f22 3342 .word cmp_fs_s_f24 3343 .word cmp_fs_s_f26 3344 .word cmp_fs_s_f28 3345 .word cmp_fs_s_f30 3346 .text 3347 3348cmp_fs_s_f0: 3349 mfc1 t0, $f0 3350 b cmp_fs_s_done 3351cmp_fs_s_f2: 3352 mfc1 t0, $f2 3353 b cmp_fs_s_done 3354cmp_fs_s_f4: 3355 mfc1 t0, $f4 3356 b cmp_fs_s_done 3357cmp_fs_s_f6: 3358 mfc1 t0, $f6 3359 b cmp_fs_s_done 3360cmp_fs_s_f8: 3361 mfc1 t0, $f8 3362 b cmp_fs_s_done 3363cmp_fs_s_f10: 3364 mfc1 t0, $f10 3365 b cmp_fs_s_done 3366cmp_fs_s_f12: 3367 mfc1 t0, $f12 3368 b cmp_fs_s_done 3369cmp_fs_s_f14: 3370 mfc1 t0, $f14 3371 b cmp_fs_s_done 3372cmp_fs_s_f16: 3373 mfc1 t0, $f16 3374 b cmp_fs_s_done 3375cmp_fs_s_f18: 3376 mfc1 t0, $f18 3377 b cmp_fs_s_done 3378cmp_fs_s_f20: 3379 mfc1 t0, $f20 3380 b cmp_fs_s_done 3381cmp_fs_s_f22: 3382 mfc1 t0, $f22 3383 b cmp_fs_s_done 3384cmp_fs_s_f24: 3385 mfc1 t0, $f24 3386 b cmp_fs_s_done 3387cmp_fs_s_f26: 3388 mfc1 t0, $f26 3389 b cmp_fs_s_done 3390cmp_fs_s_f28: 3391 mfc1 t0, $f28 3392 b cmp_fs_s_done 3393cmp_fs_s_f30: 3394 mfc1 t0, $f30 3395cmp_fs_s_done: 3396 srl t1, t0, 23 # get exponent 3397 and t1, t1, 0xFF 3398 and t2, t0, 0x7FFFFF # get fraction 3399 srl t0, t0, 31 # get sign 3400 3401 srl a3, a0, 17 - 2 # get FT field (even regs only) 3402 and a3, a3, 0xF << 2 # mask FT field 3403 lw a3, cmp_ft_s_tbl(a3) # switch on register number 3404 j a3 3405 3406 .rdata 3407cmp_ft_s_tbl: 3408 .word cmp_ft_s_f0 3409 .word cmp_ft_s_f2 3410 .word cmp_ft_s_f4 3411 .word cmp_ft_s_f6 3412 .word cmp_ft_s_f8 3413 .word cmp_ft_s_f10 3414 .word cmp_ft_s_f12 3415 .word cmp_ft_s_f14 3416 .word cmp_ft_s_f16 3417 .word cmp_ft_s_f18 3418 .word cmp_ft_s_f20 3419 .word cmp_ft_s_f22 3420 .word cmp_ft_s_f24 3421 .word cmp_ft_s_f26 3422 .word cmp_ft_s_f28 3423 .word cmp_ft_s_f30 3424 .text 3425 3426cmp_ft_s_f0: 3427 mfc1 ta0, $f0 3428 b cmp_ft_s_done 3429cmp_ft_s_f2: 3430 mfc1 ta0, $f2 3431 b cmp_ft_s_done 3432cmp_ft_s_f4: 3433 mfc1 ta0, $f4 3434 b cmp_ft_s_done 3435cmp_ft_s_f6: 3436 mfc1 ta0, $f6 3437 b cmp_ft_s_done 3438cmp_ft_s_f8: 3439 mfc1 ta0, $f8 3440 b cmp_ft_s_done 3441cmp_ft_s_f10: 3442 mfc1 ta0, $f10 3443 b cmp_ft_s_done 3444cmp_ft_s_f12: 3445 mfc1 ta0, $f12 3446 b cmp_ft_s_done 3447cmp_ft_s_f14: 3448 mfc1 ta0, $f14 3449 b cmp_ft_s_done 3450cmp_ft_s_f16: 3451 mfc1 ta0, $f16 3452 b cmp_ft_s_done 3453cmp_ft_s_f18: 3454 mfc1 ta0, $f18 3455 b cmp_ft_s_done 3456cmp_ft_s_f20: 3457 mfc1 ta0, $f20 3458 b cmp_ft_s_done 3459cmp_ft_s_f22: 3460 mfc1 ta0, $f22 3461 b cmp_ft_s_done 3462cmp_ft_s_f24: 3463 mfc1 ta0, $f24 3464 b cmp_ft_s_done 3465cmp_ft_s_f26: 3466 mfc1 ta0, $f26 3467 b cmp_ft_s_done 3468cmp_ft_s_f28: 3469 mfc1 ta0, $f28 3470 b cmp_ft_s_done 3471cmp_ft_s_f30: 3472 mfc1 ta0, $f30 3473cmp_ft_s_done: 3474 srl ta1, ta0, 23 # get exponent 3475 and ta1, ta1, 0xFF 3476 and ta2, ta0, 0x7FFFFF # get fraction 3477 srl ta0, ta0, 31 # get sign 3478 j ra 3479#endif 3480END(get_cmp_s) 3481 3482/*---------------------------------------------------------------------------- 3483 * get_cmp_d -- 3484 * 3485 * Read (double precision) the FS register (bits 15-11) and 3486 * the FT register (bits 20-16) and break up into fields. 3487 * This is an internal routine used by MachEmulateFP only. 3488 * 3489 * Results: 3490 * t0 contains the sign 3491 * t1 contains the (biased) exponent 3492 * t2 contains the fraction 3493 * t3 contains the remaining fraction 3494 * ta0 contains the sign 3495 * ta1 contains the (biased) exponent 3496 * ta2 contains the fraction 3497 * ta3 contains the remaining fraction 3498 * 3499 *---------------------------------------------------------------------------- 3500 */ 3501LEAF(get_cmp_d) 3502#ifdef SOFTFLOAT 3503 srl t1, a0, 11-2 3504 lw ta2, _C_LABEL(curpcb) # get pcb of current process 3505 andi t1, t1, 0x0078 # Even regs only 3506 addu t0, ta2, t1 3507 3508 lw t3, U_PCB_FPREGS+FRAME_FP0(t0) 3509 lw t0, U_PCB_FPREGS+FRAME_FP0+4(t0) 3510 3511 srl t1, t0, 20 # get exponent 3512 and t1, t1, 0x7FF 3513 and t2, t0, 0xFFFFF # get fraction 3514 srl t0, t0, 31 # get sign 3515 3516 srl ta0, a0, 16-2 3517 andi ta0, ta0, 0x0078 # Even regs only 3518 addu ta2, ta2, ta0 3519 3520 lw ta3, U_PCB_FPREGS+FRAME_FP0(ta2) 3521 lw ta0, U_PCB_FPREGS+FRAME_FP0+4(ta2) 3522 3523 srl ta1, ta0, 20 # get exponent 3524 and ta1, ta1, 0x7FF 3525 and ta2, ta0, 0xFFFFF # get fraction 3526 srl ta0, ta0, 31 # get sign 3527 j ra 3528#else 3529 srl a3, a0, 12 - 2 # get FS field (even regs only) 3530 and a3, a3, 0xF << 2 # mask FS field 3531 lw a3, cmp_fs_d_tbl(a3) # switch on register number 3532 j a3 3533 3534 .rdata 3535cmp_fs_d_tbl: 3536 .word cmp_fs_d_f0 3537 .word cmp_fs_d_f2 3538 .word cmp_fs_d_f4 3539 .word cmp_fs_d_f6 3540 .word cmp_fs_d_f8 3541 .word cmp_fs_d_f10 3542 .word cmp_fs_d_f12 3543 .word cmp_fs_d_f14 3544 .word cmp_fs_d_f16 3545 .word cmp_fs_d_f18 3546 .word cmp_fs_d_f20 3547 .word cmp_fs_d_f22 3548 .word cmp_fs_d_f24 3549 .word cmp_fs_d_f26 3550 .word cmp_fs_d_f28 3551 .word cmp_fs_d_f30 3552 .text 3553 3554cmp_fs_d_f0: 3555 mfc1 t3, $f0 3556 mfc1 t0, $f1 3557 b cmp_fs_d_done 3558cmp_fs_d_f2: 3559 mfc1 t3, $f2 3560 mfc1 t0, $f3 3561 b cmp_fs_d_done 3562cmp_fs_d_f4: 3563 mfc1 t3, $f4 3564 mfc1 t0, $f5 3565 b cmp_fs_d_done 3566cmp_fs_d_f6: 3567 mfc1 t3, $f6 3568 mfc1 t0, $f7 3569 b cmp_fs_d_done 3570cmp_fs_d_f8: 3571 mfc1 t3, $f8 3572 mfc1 t0, $f9 3573 b cmp_fs_d_done 3574cmp_fs_d_f10: 3575 mfc1 t3, $f10 3576 mfc1 t0, $f11 3577 b cmp_fs_d_done 3578cmp_fs_d_f12: 3579 mfc1 t3, $f12 3580 mfc1 t0, $f13 3581 b cmp_fs_d_done 3582cmp_fs_d_f14: 3583 mfc1 t3, $f14 3584 mfc1 t0, $f15 3585 b cmp_fs_d_done 3586cmp_fs_d_f16: 3587 mfc1 t3, $f16 3588 mfc1 t0, $f17 3589 b cmp_fs_d_done 3590cmp_fs_d_f18: 3591 mfc1 t3, $f18 3592 mfc1 t0, $f19 3593 b cmp_fs_d_done 3594cmp_fs_d_f20: 3595 mfc1 t3, $f20 3596 mfc1 t0, $f21 3597 b cmp_fs_d_done 3598cmp_fs_d_f22: 3599 mfc1 t3, $f22 3600 mfc1 t0, $f23 3601 b cmp_fs_d_done 3602cmp_fs_d_f24: 3603 mfc1 t3, $f24 3604 mfc1 t0, $f25 3605 b cmp_fs_d_done 3606cmp_fs_d_f26: 3607 mfc1 t3, $f26 3608 mfc1 t0, $f27 3609 b cmp_fs_d_done 3610cmp_fs_d_f28: 3611 mfc1 t3, $f28 3612 mfc1 t0, $f29 3613 b cmp_fs_d_done 3614cmp_fs_d_f30: 3615 mfc1 t3, $f30 3616 mfc1 t0, $f31 3617cmp_fs_d_done: 3618 srl t1, t0, 20 # get exponent 3619 and t1, t1, 0x7FF 3620 and t2, t0, 0xFFFFF # get fraction 3621 srl t0, t0, 31 # get sign 3622 3623 srl a3, a0, 17 - 2 # get FT field (even regs only) 3624 and a3, a3, 0xF << 2 # mask FT field 3625 lw a3, cmp_ft_d_tbl(a3) # switch on register number 3626 j a3 3627 3628 .rdata 3629cmp_ft_d_tbl: 3630 .word cmp_ft_d_f0 3631 .word cmp_ft_d_f2 3632 .word cmp_ft_d_f4 3633 .word cmp_ft_d_f6 3634 .word cmp_ft_d_f8 3635 .word cmp_ft_d_f10 3636 .word cmp_ft_d_f12 3637 .word cmp_ft_d_f14 3638 .word cmp_ft_d_f16 3639 .word cmp_ft_d_f18 3640 .word cmp_ft_d_f20 3641 .word cmp_ft_d_f22 3642 .word cmp_ft_d_f24 3643 .word cmp_ft_d_f26 3644 .word cmp_ft_d_f28 3645 .word cmp_ft_d_f30 3646 .text 3647 3648cmp_ft_d_f0: 3649 mfc1 ta3, $f0 3650 mfc1 ta0, $f1 3651 b cmp_ft_d_done 3652cmp_ft_d_f2: 3653 mfc1 ta3, $f2 3654 mfc1 ta0, $f3 3655 b cmp_ft_d_done 3656cmp_ft_d_f4: 3657 mfc1 ta3, $f4 3658 mfc1 ta0, $f5 3659 b cmp_ft_d_done 3660cmp_ft_d_f6: 3661 mfc1 ta3, $f6 3662 mfc1 ta0, $f7 3663 b cmp_ft_d_done 3664cmp_ft_d_f8: 3665 mfc1 ta3, $f8 3666 mfc1 ta0, $f9 3667 b cmp_ft_d_done 3668cmp_ft_d_f10: 3669 mfc1 ta3, $f10 3670 mfc1 ta0, $f11 3671 b cmp_ft_d_done 3672cmp_ft_d_f12: 3673 mfc1 ta3, $f12 3674 mfc1 ta0, $f13 3675 b cmp_ft_d_done 3676cmp_ft_d_f14: 3677 mfc1 ta3, $f14 3678 mfc1 ta0, $f15 3679 b cmp_ft_d_done 3680cmp_ft_d_f16: 3681 mfc1 ta3, $f16 3682 mfc1 ta0, $f17 3683 b cmp_ft_d_done 3684cmp_ft_d_f18: 3685 mfc1 ta3, $f18 3686 mfc1 ta0, $f19 3687 b cmp_ft_d_done 3688cmp_ft_d_f20: 3689 mfc1 ta3, $f20 3690 mfc1 ta0, $f21 3691 b cmp_ft_d_done 3692cmp_ft_d_f22: 3693 mfc1 ta3, $f22 3694 mfc1 ta0, $f23 3695 b cmp_ft_d_done 3696cmp_ft_d_f24: 3697 mfc1 ta3, $f24 3698 mfc1 ta0, $f25 3699 b cmp_ft_d_done 3700cmp_ft_d_f26: 3701 mfc1 ta3, $f26 3702 mfc1 ta0, $f27 3703 b cmp_ft_d_done 3704cmp_ft_d_f28: 3705 mfc1 ta3, $f28 3706 mfc1 ta0, $f29 3707 b cmp_ft_d_done 3708cmp_ft_d_f30: 3709 mfc1 ta3, $f30 3710 mfc1 ta0, $f31 3711cmp_ft_d_done: 3712 srl ta1, ta0, 20 # get exponent 3713 and ta1, ta1, 0x7FF 3714 and ta2, ta0, 0xFFFFF # get fraction 3715 srl ta0, ta0, 31 # get sign 3716 j ra 3717#endif 3718END(get_cmp_d) 3719 3720/*---------------------------------------------------------------------------- 3721 * set_fd_s -- 3722 * 3723 * Write (single precision) the FD register (bits 10-6). 3724 * This is an internal routine used by MachEmulateFP only. 3725 * 3726 * Arguments: 3727 * a0 contains the FP instruction 3728 * t0 contains the sign 3729 * t1 contains the (biased) exponent 3730 * t2 contains the fraction 3731 * 3732 * set_fd_word -- 3733 * 3734 * Write (integer) the FD register (bits 10-6). 3735 * This is an internal routine used by MachEmulateFP only. 3736 * 3737 * Arguments: 3738 * a0 contains the FP instruction 3739 * t2 contains the integer 3740 * 3741 *---------------------------------------------------------------------------- 3742 */ 3743LEAF(set_fd_s) 3744 sll t0, t0, 31 # position sign 3745 sll t1, t1, 23 # position exponent 3746 or t2, t2, t0 3747 or t2, t2, t1 3748XLEAF(set_fd_word) 3749#ifdef SOFTFLOAT 3750 srl t1, a0, 6-2 3751 lw t0, _C_LABEL(curpcb) # get pcb of current process 3752 andi t1, t1, 0x0078 # Even regs only 3753 addu t0, t0, t1 3754 3755 sw t2, U_PCB_FPREGS+FRAME_FP0(t0) 3756 j ra 3757#else 3758 srl a3, a0, 7 - 2 # get FD field (even regs only) 3759 and a3, a3, 0xF << 2 # mask FT field 3760 lw a3, set_fd_s_tbl(a3) # switch on register number 3761 j a3 3762 3763 .rdata 3764set_fd_s_tbl: 3765 .word set_fd_s_f0 3766 .word set_fd_s_f2 3767 .word set_fd_s_f4 3768 .word set_fd_s_f6 3769 .word set_fd_s_f8 3770 .word set_fd_s_f10 3771 .word set_fd_s_f12 3772 .word set_fd_s_f14 3773 .word set_fd_s_f16 3774 .word set_fd_s_f18 3775 .word set_fd_s_f20 3776 .word set_fd_s_f22 3777 .word set_fd_s_f24 3778 .word set_fd_s_f26 3779 .word set_fd_s_f28 3780 .word set_fd_s_f30 3781 .text 3782 3783set_fd_s_f0: 3784 mtc1 t2, $f0 3785 j ra 3786set_fd_s_f2: 3787 mtc1 t2, $f2 3788 j ra 3789set_fd_s_f4: 3790 mtc1 t2, $f4 3791 j ra 3792set_fd_s_f6: 3793 mtc1 t2, $f6 3794 j ra 3795set_fd_s_f8: 3796 mtc1 t2, $f8 3797 j ra 3798set_fd_s_f10: 3799 mtc1 t2, $f10 3800 j ra 3801set_fd_s_f12: 3802 mtc1 t2, $f12 3803 j ra 3804set_fd_s_f14: 3805 mtc1 t2, $f14 3806 j ra 3807set_fd_s_f16: 3808 mtc1 t2, $f16 3809 j ra 3810set_fd_s_f18: 3811 mtc1 t2, $f18 3812 j ra 3813set_fd_s_f20: 3814 mtc1 t2, $f20 3815 j ra 3816set_fd_s_f22: 3817 mtc1 t2, $f22 3818 j ra 3819set_fd_s_f24: 3820 mtc1 t2, $f24 3821 j ra 3822set_fd_s_f26: 3823 mtc1 t2, $f26 3824 j ra 3825set_fd_s_f28: 3826 mtc1 t2, $f28 3827 j ra 3828set_fd_s_f30: 3829 mtc1 t2, $f30 3830 j ra 3831#endif 3832END(set_fd_s) 3833 3834/*---------------------------------------------------------------------------- 3835 * set_fd_d -- 3836 * 3837 * Write (double precision) the FT register (bits 10-6). 3838 * This is an internal routine used by MachEmulateFP only. 3839 * 3840 * Arguments: 3841 * a0 contains the FP instruction 3842 * t0 contains the sign 3843 * t1 contains the (biased) exponent 3844 * t2 contains the fraction 3845 * t3 contains the remaining fraction 3846 * 3847 *---------------------------------------------------------------------------- 3848 */ 3849LEAF(set_fd_d) 3850#ifdef SOFTFLOAT 3851 sll t0, t0, 31 # set sign 3852 sll t1, t1, 20 # set exponent 3853 or t0, t0, t1 3854 or t0, t0, t2 # set fraction 3855 3856 srl t1, a0, 6-2 3857 lw t2, _C_LABEL(curpcb) # get pcb of current process 3858 andi t1, t1, 0x0078 # Even regs only 3859 addu t2, t2, t1 3860 3861 sw t3, U_PCB_FPREGS+FRAME_FP0(t2) 3862 sw t0, U_PCB_FPREGS+FRAME_FP0+4(t2) 3863 j ra 3864#else 3865 sll t0, t0, 31 # set sign 3866 sll t1, t1, 20 # set exponent 3867 or t0, t0, t1 3868 or t0, t0, t2 # set fraction 3869 srl a3, a0, 7 - 2 # get FD field (even regs only) 3870 and a3, a3, 0xF << 2 # mask FD field 3871 lw a3, set_fd_d_tbl(a3) # switch on register number 3872 j a3 3873 3874 .rdata 3875set_fd_d_tbl: 3876 .word set_fd_d_f0 3877 .word set_fd_d_f2 3878 .word set_fd_d_f4 3879 .word set_fd_d_f6 3880 .word set_fd_d_f8 3881 .word set_fd_d_f10 3882 .word set_fd_d_f12 3883 .word set_fd_d_f14 3884 .word set_fd_d_f16 3885 .word set_fd_d_f18 3886 .word set_fd_d_f20 3887 .word set_fd_d_f22 3888 .word set_fd_d_f24 3889 .word set_fd_d_f26 3890 .word set_fd_d_f28 3891 .word set_fd_d_f30 3892 .text 3893 3894set_fd_d_f0: 3895 mtc1 t3, $f0 3896 mtc1 t0, $f1 3897 j ra 3898set_fd_d_f2: 3899 mtc1 t3, $f2 3900 mtc1 t0, $f3 3901 j ra 3902set_fd_d_f4: 3903 mtc1 t3, $f4 3904 mtc1 t0, $f5 3905 j ra 3906set_fd_d_f6: 3907 mtc1 t3, $f6 3908 mtc1 t0, $f7 3909 j ra 3910set_fd_d_f8: 3911 mtc1 t3, $f8 3912 mtc1 t0, $f9 3913 j ra 3914set_fd_d_f10: 3915 mtc1 t3, $f10 3916 mtc1 t0, $f11 3917 j ra 3918set_fd_d_f12: 3919 mtc1 t3, $f12 3920 mtc1 t0, $f13 3921 j ra 3922set_fd_d_f14: 3923 mtc1 t3, $f14 3924 mtc1 t0, $f15 3925 j ra 3926set_fd_d_f16: 3927 mtc1 t3, $f16 3928 mtc1 t0, $f17 3929 j ra 3930set_fd_d_f18: 3931 mtc1 t3, $f18 3932 mtc1 t0, $f19 3933 j ra 3934set_fd_d_f20: 3935 mtc1 t3, $f20 3936 mtc1 t0, $f21 3937 j ra 3938set_fd_d_f22: 3939 mtc1 t3, $f22 3940 mtc1 t0, $f23 3941 j ra 3942set_fd_d_f24: 3943 mtc1 t3, $f24 3944 mtc1 t0, $f25 3945 j ra 3946set_fd_d_f26: 3947 mtc1 t3, $f26 3948 mtc1 t0, $f27 3949 j ra 3950set_fd_d_f28: 3951 mtc1 t3, $f28 3952 mtc1 t0, $f29 3953 j ra 3954set_fd_d_f30: 3955 mtc1 t3, $f30 3956 mtc1 t0, $f31 3957 j ra 3958#endif 3959END(set_fd_d) 3960 3961/*---------------------------------------------------------------------------- 3962 * renorm_fs_s -- 3963 * 3964 * Results: 3965 * t1 unbiased exponent 3966 * t2 normalized fraction 3967 * 3968 *---------------------------------------------------------------------------- 3969 */ 3970LEAF(renorm_fs_s) 3971/* 3972 * Find out how many leading zero bits are in t2 and put in t9. 3973 */ 3974 move v0, t2 3975 move t9, zero 3976 srl v1, v0, 16 3977 bne v1, zero, 1f 3978 addu t9, 16 3979 sll v0, 16 39801: 3981 srl v1, v0, 24 3982 bne v1, zero, 1f 3983 addu t9, 8 3984 sll v0, 8 39851: 3986 srl v1, v0, 28 3987 bne v1, zero, 1f 3988 addu t9, 4 3989 sll v0, 4 39901: 3991 srl v1, v0, 30 3992 bne v1, zero, 1f 3993 addu t9, 2 3994 sll v0, 2 39951: 3996 srl v1, v0, 31 3997 bne v1, zero, 1f 3998 addu t9, 1 3999/* 4000 * Now shift t2 the correct number of bits. 4001 */ 40021: 4003 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros 4004 li t1, SEXP_MIN 4005 subu t1, t1, t9 # adjust exponent 4006 sll t2, t2, t9 4007 j ra 4008END(renorm_fs_s) 4009 4010/*---------------------------------------------------------------------------- 4011 * renorm_fs_d -- 4012 * 4013 * Results: 4014 * t1 unbiased exponent 4015 * t2,t3 normalized fraction 4016 * 4017 *---------------------------------------------------------------------------- 4018 */ 4019LEAF(renorm_fs_d) 4020/* 4021 * Find out how many leading zero bits are in t2,t3 and put in t9. 4022 */ 4023 move v0, t2 4024 move t9, zero 4025 bne t2, zero, 1f 4026 move v0, t3 4027 addu t9, 32 40281: 4029 srl v1, v0, 16 4030 bne v1, zero, 1f 4031 addu t9, 16 4032 sll v0, 16 40331: 4034 srl v1, v0, 24 4035 bne v1, zero, 1f 4036 addu t9, 8 4037 sll v0, 8 40381: 4039 srl v1, v0, 28 4040 bne v1, zero, 1f 4041 addu t9, 4 4042 sll v0, 4 40431: 4044 srl v1, v0, 30 4045 bne v1, zero, 1f 4046 addu t9, 2 4047 sll v0, 2 40481: 4049 srl v1, v0, 31 4050 bne v1, zero, 1f 4051 addu t9, 1 4052/* 4053 * Now shift t2,t3 the correct number of bits. 4054 */ 40551: 4056 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros 4057 li t1, DEXP_MIN 4058 subu t1, t1, t9 # adjust exponent 4059 li v0, 32 4060 blt t9, v0, 1f 4061 subu t9, t9, v0 # shift fraction left >= 32 bits 4062 sll t2, t3, t9 4063 move t3, zero 4064 j ra 40651: 4066 subu v0, v0, t9 # shift fraction left < 32 bits 4067 sll t2, t2, t9 4068 srl v1, t3, v0 4069 or t2, t2, v1 4070 sll t3, t3, t9 4071 j ra 4072END(renorm_fs_d) 4073 4074/*---------------------------------------------------------------------------- 4075 * renorm_ft_s -- 4076 * 4077 * Results: 4078 * ta1 unbiased exponent 4079 * ta2 normalized fraction 4080 * 4081 *---------------------------------------------------------------------------- 4082 */ 4083LEAF(renorm_ft_s) 4084/* 4085 * Find out how many leading zero bits are in ta2 and put in t9. 4086 */ 4087 move v0, ta2 4088 move t9, zero 4089 srl v1, v0, 16 4090 bne v1, zero, 1f 4091 addu t9, 16 4092 sll v0, 16 40931: 4094 srl v1, v0, 24 4095 bne v1, zero, 1f 4096 addu t9, 8 4097 sll v0, 8 40981: 4099 srl v1, v0, 28 4100 bne v1, zero, 1f 4101 addu t9, 4 4102 sll v0, 4 41031: 4104 srl v1, v0, 30 4105 bne v1, zero, 1f 4106 addu t9, 2 4107 sll v0, 2 41081: 4109 srl v1, v0, 31 4110 bne v1, zero, 1f 4111 addu t9, 1 4112/* 4113 * Now shift ta2 the correct number of bits. 4114 */ 41151: 4116 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros 4117 li ta1, SEXP_MIN 4118 subu ta1, ta1, t9 # adjust exponent 4119 sll ta2, ta2, t9 4120 j ra 4121END(renorm_ft_s) 4122 4123/*---------------------------------------------------------------------------- 4124 * renorm_ft_d -- 4125 * 4126 * Results: 4127 * ta1 unbiased exponent 4128 * ta2,ta3 normalized fraction 4129 * 4130 *---------------------------------------------------------------------------- 4131 */ 4132LEAF(renorm_ft_d) 4133/* 4134 * Find out how many leading zero bits are in ta2,ta3 and put in t9. 4135 */ 4136 move v0, ta2 4137 move t9, zero 4138 bne ta2, zero, 1f 4139 move v0, ta3 4140 addu t9, 32 41411: 4142 srl v1, v0, 16 4143 bne v1, zero, 1f 4144 addu t9, 16 4145 sll v0, 16 41461: 4147 srl v1, v0, 24 4148 bne v1, zero, 1f 4149 addu t9, 8 4150 sll v0, 8 41511: 4152 srl v1, v0, 28 4153 bne v1, zero, 1f 4154 addu t9, 4 4155 sll v0, 4 41561: 4157 srl v1, v0, 30 4158 bne v1, zero, 1f 4159 addu t9, 2 4160 sll v0, 2 41611: 4162 srl v1, v0, 31 4163 bne v1, zero, 1f 4164 addu t9, 1 4165/* 4166 * Now shift ta2,ta3 the correct number of bits. 4167 */ 41681: 4169 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros 4170 li ta1, DEXP_MIN 4171 subu ta1, ta1, t9 # adjust exponent 4172 li v0, 32 4173 blt t9, v0, 1f 4174 subu t9, t9, v0 # shift fraction left >= 32 bits 4175 sll ta2, ta3, t9 4176 move ta3, zero 4177 j ra 41781: 4179 subu v0, v0, t9 # shift fraction left < 32 bits 4180 sll ta2, ta2, t9 4181 srl v1, ta3, v0 4182 or ta2, ta2, v1 4183 sll ta3, ta3, t9 4184 j ra 4185END(renorm_ft_d) 4186 4187#ifdef SOFTFLOAT 4188/* 4189 * Emulate branch delay slot CPU instruction. 4190 * Enter from BC1x emulation. 4191 * These instructions are not implemented and causes SIGILL. 4192 * jump/branch 4193 * COP0 4194 * 64bit operation 4195 * trap/syscall/break 4196 * 4197 * Args are same as MachEmulateFP. 4198 * It should be used to emulate instruction in branch delay slot. 4199 */ 4200LEAF(bcemul_delay_slot) 4201 REG_PROLOGUE 4202 REG_S zero, FRAME_ZERO(a1) # ensure zero has value 0 4203 REG_EPILOGUE 4204 4205 srl t0, a0, 26-2 4206 andi t0, t0, 0x00FC 4207 lw t0, bcemul_optbl(t0) 4208 j t0 4209 4210bcemul_special: 4211 sll t0, a0, 2 4212 andi t0, t0, 0x00FC 4213 lw t0, bcemul_specialtbl(t0) 4214 j t0 4215 4216 .rdata 4217bcemul_optbl: 4218 .word bcemul_special # 0 4219 .word _C_LABEL(bcemul_sigill) # 1 4220 .word _C_LABEL(bcemul_sigill) # 2 4221 .word _C_LABEL(bcemul_sigill) # 3 4222 .word _C_LABEL(bcemul_sigill) # 4 4223 .word _C_LABEL(bcemul_sigill) # 5 4224 .word _C_LABEL(bcemul_sigill) # 6 4225 .word _C_LABEL(bcemul_sigill) # 7 4226 .word bcemul_addi # 8 4227 .word bcemul_addiu # 9 4228 .word bcemul_slti # 10 4229 .word bcemul_sltiu # 11 4230 .word bcemul_andi # 12 4231 .word bcemul_ori # 13 4232 .word bcemul_xori # 14 4233 .word bcemul_lui # 15 4234 .word _C_LABEL(bcemul_sigill) # 16 4235 .word _C_LABEL(MachEmulateFP) # 17 4236 .word _C_LABEL(bcemul_sigill) # 18 4237 .word _C_LABEL(bcemul_sigill) # 19 4238 .word _C_LABEL(bcemul_sigill) # 20 4239 .word _C_LABEL(bcemul_sigill) # 21 4240 .word _C_LABEL(bcemul_sigill) # 22 4241 .word _C_LABEL(bcemul_sigill) # 23 4242 .word _C_LABEL(bcemul_sigill) # 24 4243 .word _C_LABEL(bcemul_sigill) # 25 4244 .word _C_LABEL(bcemul_sigill) # 26 4245 .word _C_LABEL(bcemul_sigill) # 27 4246 .word _C_LABEL(bcemul_sigill) # 28 4247 .word _C_LABEL(bcemul_sigill) # 29 4248 .word _C_LABEL(bcemul_sigill) # 30 4249 .word _C_LABEL(bcemul_sigill) # 31 4250 .word _C_LABEL(bcemul_lb) # 32 4251 .word _C_LABEL(bcemul_lh) # 33 4252 .word _C_LABEL(bcemul_lwl) # 34 4253 .word _C_LABEL(bcemul_lw) # 35 4254 .word _C_LABEL(bcemul_lbu) # 36 4255 .word _C_LABEL(bcemul_lhu) # 37 4256 .word _C_LABEL(bcemul_lwr) # 38 4257 .word _C_LABEL(bcemul_sigill) # 39 4258 .word _C_LABEL(bcemul_sb) # 40 4259 .word _C_LABEL(bcemul_sh) # 41 4260 .word _C_LABEL(bcemul_swl) # 42 4261 .word _C_LABEL(bcemul_sw) # 43 4262 .word _C_LABEL(bcemul_sigill) # 44 4263 .word _C_LABEL(bcemul_sigill) # 45 4264 .word _C_LABEL(bcemul_swr) # 46 4265 .word _C_LABEL(bcemul_sigill) # 47 4266 .word _C_LABEL(bcemul_sigill) # 48 4267 .word _C_LABEL(MachEmulateLWC1) # 49 4268 .word _C_LABEL(bcemul_sigill) # 50 4269 .word _C_LABEL(bcemul_sigill) # 51 4270 .word _C_LABEL(bcemul_sigill) # 52 4271 .word _C_LABEL(MachEmulateLDC1) # 53 4272 .word _C_LABEL(bcemul_sigill) # 54 4273 .word _C_LABEL(bcemul_sigill) # 55 4274 .word _C_LABEL(bcemul_sigill) # 56 4275 .word _C_LABEL(MachEmulateSWC1) # 57 4276 .word _C_LABEL(bcemul_sigill) # 58 4277 .word _C_LABEL(bcemul_sigill) # 59 4278 .word _C_LABEL(bcemul_sigill) # 60 4279 .word _C_LABEL(MachEmulateSDC1) # 61 4280 .word _C_LABEL(bcemul_sigill) # 62 4281 .word _C_LABEL(bcemul_sigill) # 63 4282 4283bcemul_specialtbl: 4284 .word bcemul_sll # 0 4285 .word _C_LABEL(bcemul_sigill) # 1 4286 .word bcemul_srl # 2 4287 .word bcemul_sra # 3 4288 .word bcemul_sllv # 4 4289 .word _C_LABEL(bcemul_sigill) # 5 4290 .word bcemul_srlv # 6 4291 .word bcemul_srav # 7 4292 .word _C_LABEL(bcemul_sigill) # 8 4293 .word _C_LABEL(bcemul_sigill) # 9 4294 .word _C_LABEL(bcemul_sigill) # 10 4295 .word _C_LABEL(bcemul_sigill) # 11 4296 .word _C_LABEL(bcemul_sigill) # 12 4297 .word _C_LABEL(bcemul_sigill) # 13 4298 .word _C_LABEL(bcemul_sigill) # 14 4299 .word bcemul_sync # 15 4300 .word bcemul_mfhi # 16 4301 .word bcemul_mthi # 17 4302 .word bcemul_mflo # 18 4303 .word bcemul_mtlo # 19 4304 .word _C_LABEL(bcemul_sigill) # 20 4305 .word _C_LABEL(bcemul_sigill) # 21 4306 .word _C_LABEL(bcemul_sigill) # 22 4307 .word _C_LABEL(bcemul_sigill) # 23 4308 .word bcemul_mult # 24 4309 .word bcemul_multu # 25 4310 .word bcemul_div # 26 4311 .word bcemul_divu # 27 4312 .word _C_LABEL(bcemul_sigill) # 28 4313 .word _C_LABEL(bcemul_sigill) # 29 4314 .word _C_LABEL(bcemul_sigill) # 30 4315 .word _C_LABEL(bcemul_sigill) # 31 4316 .word bcemul_add # 32 4317 .word bcemul_addu # 33 4318 .word bcemul_sub # 34 4319 .word bcemul_subu # 35 4320 .word bcemul_and # 36 4321 .word bcemul_or # 37 4322 .word bcemul_xor # 38 4323 .word bcemul_nor # 39 4324 .word _C_LABEL(bcemul_sigill) # 40 4325 .word _C_LABEL(bcemul_sigill) # 41 4326 .word bcemul_slt # 42 4327 .word bcemul_sltu # 43 4328 .word _C_LABEL(bcemul_sigill) # 44 4329 .word _C_LABEL(bcemul_sigill) # 45 4330 .word _C_LABEL(bcemul_sigill) # 46 4331 .word _C_LABEL(bcemul_sigill) # 47 4332 .word _C_LABEL(bcemul_sigill) # 48 4333 .word _C_LABEL(bcemul_sigill) # 49 4334 .word _C_LABEL(bcemul_sigill) # 50 4335 .word _C_LABEL(bcemul_sigill) # 51 4336 .word _C_LABEL(bcemul_sigill) # 52 4337 .word _C_LABEL(bcemul_sigill) # 53 4338 .word _C_LABEL(bcemul_sigill) # 54 4339 .word _C_LABEL(bcemul_sigill) # 55 4340 .word _C_LABEL(bcemul_sigill) # 56 4341 .word _C_LABEL(bcemul_sigill) # 57 4342 .word _C_LABEL(bcemul_sigill) # 58 4343 .word _C_LABEL(bcemul_sigill) # 59 4344 .word _C_LABEL(bcemul_sigill) # 60 4345 .word _C_LABEL(bcemul_sigill) # 61 4346 .word _C_LABEL(bcemul_sigill) # 62 4347 .word _C_LABEL(bcemul_sigill) # 63 4348 4349 .text 4350 4351bcemul_addi: 4352 srl t0, a0, 21-SZREG_SHFT # rs 4353 srl t1, a0, 16-SZREG_SHFT # rt 4354 andi t0, t0, SZREG_MASK 4355 andi t1, t1, SZREG_MASK 4356 addu t0, a1, t0 4357 addu t1, a1, t1 4358 sll t2, a0, 16 4359 sra t2, t2, 16 4360 REG_PROLOGUE 4361 REG_L v0, FRAME_ZERO(t0) 4362 REG_EPILOGUE 4363 addu t0, v0, t2 4364 4365 /* Overflow check */ 4366 xor t2, v0, t2 4367 srl t2, t2, 31 4368 bne t2, zero, addiok 4369 4370 xor v0, v0, t0 4371 srl v0, v0, 31 4372 beq v0, zero, addiok 4373 4374 j _C_LABEL(bcemul_sigfpe) 4375 4376addiok: 4377 REG_PROLOGUE 4378 REG_S t0, FRAME_ZERO(t1) 4379 REG_EPILOGUE 4380 b bcemul_done 4381 4382bcemul_addiu: 4383 srl t0, a0, 21-SZREG_SHFT # rs 4384 srl t1, a0, 16-SZREG_SHFT # rt 4385 andi t0, t0, SZREG_MASK 4386 andi t1, t1, SZREG_MASK 4387 addu t0, a1, t0 4388 addu t1, a1, t1 4389 sll t2, a0, 16 4390 sra t2, t2, 16 4391 REG_PROLOGUE 4392 REG_L v0, FRAME_ZERO(t0) 4393 addu v0, v0, t2 4394 REG_S v0, FRAME_ZERO(t1) 4395 REG_EPILOGUE 4396 b bcemul_done 4397 4398bcemul_slti: 4399 srl t0, a0, 21-SZREG_SHFT # rs 4400 srl t1, a0, 16-SZREG_SHFT # rt 4401 andi t0, t0, SZREG_MASK 4402 andi t1, t1, SZREG_MASK 4403 addu t0, a1, t0 4404 addu t1, a1, t1 4405 sll t2, a0, 16 4406 sra t2, t2, 16 4407 REG_PROLOGUE 4408 REG_L v0, FRAME_ZERO(t0) 4409 slt v0, v0, t2 4410 REG_S v0, FRAME_ZERO(t1) 4411 REG_EPILOGUE 4412 b bcemul_done 4413 4414bcemul_sltiu: 4415 srl t0, a0, 21-SZREG_SHFT # rs 4416 srl t1, a0, 16-SZREG_SHFT # rt 4417 andi t0, t0, SZREG_MASK 4418 andi t1, t1, SZREG_MASK 4419 addu t0, a1, t0 4420 addu t1, a1, t1 4421 sll t2, a0, 16 4422 sra t2, t2, 16 4423 REG_PROLOGUE 4424 REG_L v0, FRAME_ZERO(t0) 4425 sltu v0, v0, t2 4426 REG_S v0, FRAME_ZERO(t1) 4427 REG_EPILOGUE 4428 b bcemul_done 4429 4430bcemul_andi: 4431 srl t0, a0, 21-SZREG_SHFT # rs 4432 srl t1, a0, 16-SZREG_SHFT # rt 4433 andi t0, t0, SZREG_MASK 4434 andi t1, t1, SZREG_MASK 4435 addu t0, a1, t0 4436 addu t1, a1, t1 4437 andi t2, a0, 0xFFFF 4438 REG_PROLOGUE 4439 REG_L v0, FRAME_ZERO(t0) 4440 and v0, v0, t2 4441 REG_S v0, FRAME_ZERO(t1) 4442 REG_EPILOGUE 4443 b bcemul_done 4444 4445bcemul_ori: 4446 srl t0, a0, 21-SZREG_SHFT # rs 4447 srl t1, a0, 16-SZREG_SHFT # rt 4448 andi t0, t0, SZREG_MASK 4449 andi t1, t1, SZREG_MASK 4450 addu t0, a1, t0 4451 addu t1, a1, t1 4452 andi t2, a0, 0xFFFF 4453 REG_PROLOGUE 4454 REG_L v0, FRAME_ZERO(t0) 4455 or v0, v0, t2 4456 REG_S v0, FRAME_ZERO(t1) 4457 REG_EPILOGUE 4458 b bcemul_done 4459 4460bcemul_xori: 4461 srl t0, a0, 21-SZREG_SHFT # rs 4462 srl t1, a0, 16-SZREG_SHFT # rt 4463 andi t0, t0, SZREG_MASK 4464 andi t1, t1, SZREG_MASK 4465 addu t0, a1, t0 4466 addu t1, a1, t1 4467 andi t2, a0, 0xFFFF 4468 REG_PROLOGUE 4469 REG_L v0, FRAME_ZERO(t0) 4470 xor v0, v0, t2 4471 REG_S v0, FRAME_ZERO(t1) 4472 REG_EPILOGUE 4473 b bcemul_done 4474 4475bcemul_lui: 4476 srl t0, a0, 16-SZREG_SHFT # rt 4477 andi t0, t0, SZREG_MASK 4478 addu t0, a1, t0 4479 sll v0, a0, 16 4480 REG_PROLOGUE 4481 REG_S v0, FRAME_ZERO(t0) 4482 REG_EPILOGUE 4483 b bcemul_done 4484 4485bcemul_sll: 4486 srl t0, a0, 16-SZREG_SHFT # rt 4487 srl t1, a0, 11-SZREG_SHFT # rd 4488 srl t2, a0, 6 # sa 4489 andi t0, t0, SZREG_MASK 4490 andi t1, t1, SZREG_MASK 4491 andi t2, t2, 0x001F 4492 addu t0, a1, t0 4493 addu t1, a1, t1 4494 REG_PROLOGUE 4495 REG_L v0, FRAME_ZERO(t0) 4496 sllv v0, v0, t2 4497 REG_S v0, FRAME_ZERO(t1) 4498 REG_EPILOGUE 4499 b bcemul_done 4500 4501bcemul_srl: 4502 srl t0, a0, 16-SZREG_SHFT # rt 4503 srl t1, a0, 11-SZREG_SHFT # rd 4504 srl t2, a0, 6 # sa 4505 andi t0, t0, SZREG_MASK 4506 andi t1, t1, SZREG_MASK 4507 andi t2, t2, 0x001F 4508 addu t0, a1, t0 4509 addu t1, a1, t1 4510 REG_PROLOGUE 4511 REG_L v0, FRAME_ZERO(t0) 4512 srlv v0, v0, t2 4513 REG_S v0, FRAME_ZERO(t1) 4514 REG_EPILOGUE 4515 b bcemul_done 4516 4517bcemul_sra: 4518 srl t0, a0, 16-SZREG_SHFT # rt 4519 srl t1, a0, 11-SZREG_SHFT # rd 4520 srl t2, a0, 6 # sa 4521 andi t0, t0, SZREG_MASK 4522 andi t1, t1, SZREG_MASK 4523 andi t2, t2, 0x001F 4524 addu t0, a1, t0 4525 addu t1, a1, t1 4526 REG_PROLOGUE 4527 REG_L v0, FRAME_ZERO(t0) 4528 srav v0, v0, t2 4529 REG_S v0, FRAME_ZERO(t1) 4530 REG_EPILOGUE 4531 b bcemul_done 4532 4533bcemul_sllv: 4534 srl t0, a0, 21-SZREG_SHFT # rs 4535 srl t1, a0, 16-SZREG_SHFT # rt 4536 srl t2, a0, 11-SZREG_SHFT # rd 4537 andi t0, t0, SZREG_MASK 4538 andi t1, t1, SZREG_MASK 4539 andi t2, t2, SZREG_MASK 4540 addu t0, a1, t0 4541 addu t1, a1, t1 4542 addu t2, a1, t2 4543 REG_PROLOGUE 4544 REG_L v0, FRAME_ZERO(t0) 4545 REG_L v1, FRAME_ZERO(t1) 4546 sllv v0, v1, v0 4547 REG_S v0, FRAME_ZERO(t2) 4548 REG_EPILOGUE 4549 b bcemul_done 4550 4551bcemul_srlv: 4552 srl t0, a0, 21-SZREG_SHFT # rs 4553 srl t1, a0, 16-SZREG_SHFT # rt 4554 srl t2, a0, 11-SZREG_SHFT # rd 4555 andi t0, t0, SZREG_MASK 4556 andi t1, t1, SZREG_MASK 4557 andi t2, t2, SZREG_MASK 4558 addu t0, a1, t0 4559 addu t1, a1, t1 4560 addu t2, a1, t2 4561 REG_PROLOGUE 4562 REG_L v0, FRAME_ZERO(t0) 4563 REG_L v1, FRAME_ZERO(t1) 4564 srlv v0, v1, v0 4565 REG_S v0, FRAME_ZERO(t2) 4566 REG_EPILOGUE 4567 b bcemul_done 4568 4569bcemul_srav: 4570 srl t0, a0, 21-SZREG_SHFT # rs 4571 srl t1, a0, 16-SZREG_SHFT # rt 4572 srl t2, a0, 11-SZREG_SHFT # rd 4573 andi t0, t0, SZREG_MASK 4574 andi t1, t1, SZREG_MASK 4575 andi t2, t2, SZREG_MASK 4576 addu t0, a1, t0 4577 addu t1, a1, t1 4578 addu t2, a1, t2 4579 REG_PROLOGUE 4580 REG_L v0, FRAME_ZERO(t0) 4581 REG_L v1, FRAME_ZERO(t1) 4582 srav v0, v1, v0 4583 REG_S v0, FRAME_ZERO(t2) 4584 REG_EPILOGUE 4585 b bcemul_done 4586 4587bcemul_sync: 4588 b bcemul_done 4589 4590bcemul_mfhi: 4591 srl t0, a0, 11-SZREG_SHFT # rd 4592 andi t0, t0, SZREG_MASK 4593 addu t0, a1, t0 4594 REG_PROLOGUE 4595 REG_L v0, FRAME_MULHI(a1) 4596 REG_S v0, FRAME_ZERO(t0) 4597 REG_EPILOGUE 4598 b bcemul_done 4599 4600bcemul_mthi: 4601 srl t0, a0, 21-SZREG_SHFT # rs 4602 andi t0, t0, SZREG_MASK 4603 addu t0, a1, t0 4604 REG_PROLOGUE 4605 REG_L v0, FRAME_ZERO(t0) 4606 REG_S v0, FRAME_MULHI(a1) 4607 REG_EPILOGUE 4608 b bcemul_done 4609 4610bcemul_mflo: 4611 srl t0, a0, 11-SZREG_SHFT # rd 4612 andi t0, t0, SZREG_MASK 4613 addu t0, a1, t0 4614 REG_PROLOGUE 4615 REG_L v0, FRAME_MULLO(a1) 4616 REG_S v0, FRAME_ZERO(t0) 4617 REG_EPILOGUE 4618 b bcemul_done 4619 4620bcemul_mtlo: 4621 srl t0, a0, 21-SZREG_SHFT # rs 4622 andi t0, t0, SZREG_MASK 4623 addu t0, a1, t0 4624 REG_PROLOGUE 4625 REG_L v0, FRAME_ZERO(t0) 4626 REG_S v0, FRAME_MULLO(a1) 4627 REG_EPILOGUE 4628 b bcemul_done 4629 4630bcemul_mult: 4631 srl t0, a0, 21-SZREG_SHFT # rs 4632 srl t1, a0, 16-SZREG_SHFT # rt 4633 andi t0, t0, SZREG_MASK 4634 andi t1, t1, SZREG_MASK 4635 addu t0, a1, t0 4636 addu t1, a1, t1 4637 REG_PROLOGUE 4638 REG_L v0, FRAME_ZERO(t0) 4639 REG_L v1, FRAME_ZERO(t1) 4640 REG_EPILOGUE 4641 mult v0, v1 4642 mflo v0 4643 mfhi v1 4644 REG_PROLOGUE 4645 REG_S v0, FRAME_MULLO(a1) 4646 REG_S v1, FRAME_MULHI(a1) 4647 REG_EPILOGUE 4648 b bcemul_done 4649 4650bcemul_multu: 4651 srl t0, a0, 21-SZREG_SHFT # rs 4652 srl t1, a0, 16-SZREG_SHFT # rt 4653 andi t0, t0, SZREG_MASK 4654 andi t1, t1, SZREG_MASK 4655 addu t0, a1, t0 4656 addu t1, a1, t1 4657 REG_PROLOGUE 4658 REG_L v0, FRAME_ZERO(t0) 4659 REG_L v1, FRAME_ZERO(t1) 4660 REG_EPILOGUE 4661 multu v0, v1 4662 mflo v0 4663 mfhi v1 4664 REG_PROLOGUE 4665 REG_S v0, FRAME_MULLO(a1) 4666 REG_S v1, FRAME_MULHI(a1) 4667 REG_EPILOGUE 4668 b bcemul_done 4669 4670bcemul_div: 4671 srl t0, a0, 21-SZREG_SHFT # rs 4672 srl t1, a0, 16-SZREG_SHFT # rt 4673 andi t0, t0, SZREG_MASK 4674 andi t1, t1, SZREG_MASK 4675 addu t0, a1, t0 4676 addu t1, a1, t1 4677 REG_PROLOGUE 4678 REG_L v0, FRAME_ZERO(t0) 4679 REG_L v1, FRAME_ZERO(t1) 4680 REG_EPILOGUE 4681 div v0, v1 4682 mflo v0 4683 mfhi v1 4684 REG_PROLOGUE 4685 REG_S v0, FRAME_MULLO(a1) 4686 REG_S v1, FRAME_MULHI(a1) 4687 REG_EPILOGUE 4688 b bcemul_done 4689 4690bcemul_divu: 4691 srl t0, a0, 21-SZREG_SHFT # rs 4692 srl t1, a0, 16-SZREG_SHFT # rt 4693 andi t0, t0, SZREG_MASK 4694 andi t1, t1, SZREG_MASK 4695 addu t0, a1, t0 4696 addu t1, a1, t1 4697 REG_PROLOGUE 4698 REG_L v0, FRAME_ZERO(t0) 4699 REG_L v1, FRAME_ZERO(t1) 4700 REG_EPILOGUE 4701 divu v0, v1 4702 mflo v0 4703 mfhi v1 4704 REG_PROLOGUE 4705 REG_S v0, FRAME_MULLO(a1) 4706 REG_S v1, FRAME_MULHI(a1) 4707 REG_EPILOGUE 4708 b bcemul_done 4709 4710bcemul_add: 4711 srl t0, a0, 21-SZREG_SHFT # rs 4712 srl t1, a0, 16-SZREG_SHFT # rt 4713 srl t2, a0, 11-SZREG_SHFT # rd 4714 andi t0, t0, SZREG_MASK 4715 andi t1, t1, SZREG_MASK 4716 andi t2, t2, SZREG_MASK 4717 addu t0, a1, t0 4718 addu t1, a1, t1 4719 addu t2, a1, t2 4720 REG_PROLOGUE 4721 REG_L v0, FRAME_ZERO(t0) 4722 REG_L v1, FRAME_ZERO(t1) 4723 REG_EPILOGUE 4724 addu t0, v0, v1 4725 4726 /* Overflow check */ 4727 xor v1, v0, v1 4728 srl v1, v1, 31 4729 bne v1, zero, addok 4730 4731 xor v0, v0, t0 4732 srl v0, v0, 31 4733 beq v0, zero, addok 4734 4735 j _C_LABEL(bcemul_sigfpe) 4736 4737addok: 4738 REG_PROLOGUE 4739 REG_S t0, FRAME_ZERO(t2) 4740 REG_EPILOGUE 4741 b bcemul_done 4742 4743bcemul_addu: 4744 srl t0, a0, 21-SZREG_SHFT # rs 4745 srl t1, a0, 16-SZREG_SHFT # rt 4746 srl t2, a0, 11-SZREG_SHFT # rd 4747 andi t0, t0, SZREG_MASK 4748 andi t1, t1, SZREG_MASK 4749 andi t2, t2, SZREG_MASK 4750 addu t0, a1, t0 4751 addu t1, a1, t1 4752 addu t2, a1, t2 4753 REG_PROLOGUE 4754 REG_L v0, FRAME_ZERO(t0) 4755 REG_L v1, FRAME_ZERO(t1) 4756 addu v0, v0, v1 4757 REG_S v0, FRAME_ZERO(t2) 4758 REG_EPILOGUE 4759 b bcemul_done 4760 4761bcemul_sub: 4762 srl t0, a0, 21-SZREG_SHFT # rs 4763 srl t1, a0, 16-SZREG_SHFT # rt 4764 srl t2, a0, 11-SZREG_SHFT # rd 4765 andi t0, t0, SZREG_MASK 4766 andi t1, t1, SZREG_MASK 4767 andi t2, t2, SZREG_MASK 4768 addu t0, a1, t0 4769 addu t1, a1, t1 4770 addu t2, a1, t2 4771 REG_PROLOGUE 4772 REG_L v0, FRAME_ZERO(t0) 4773 REG_L v1, FRAME_ZERO(t1) 4774 REG_EPILOGUE 4775 subu t0, v0, v1 4776 4777 /* Overflow check */ 4778 xor v1, v0, v1 4779 srl v1, v1, 31 4780 beq v1, zero, subok 4781 4782 xor v0, v0, t0 4783 srl v0, v0, 31 4784 beq v0, zero, subok 4785 4786 j _C_LABEL(bcemul_sigfpe) 4787 4788subok: 4789 REG_PROLOGUE 4790 REG_S t0, FRAME_ZERO(t2) 4791 REG_EPILOGUE 4792 b bcemul_done 4793 4794bcemul_subu: 4795 srl t0, a0, 21-SZREG_SHFT # rs 4796 srl t1, a0, 16-SZREG_SHFT # rt 4797 srl t2, a0, 11-SZREG_SHFT # rd 4798 andi t0, t0, SZREG_MASK 4799 andi t1, t1, SZREG_MASK 4800 andi t2, t2, SZREG_MASK 4801 addu t0, a1, t0 4802 addu t1, a1, t1 4803 addu t2, a1, t2 4804 REG_PROLOGUE 4805 REG_L v0, FRAME_ZERO(t0) 4806 REG_L v1, FRAME_ZERO(t1) 4807 subu v0, v0, v1 4808 REG_S v0, FRAME_ZERO(t2) 4809 REG_EPILOGUE 4810 b bcemul_done 4811 4812bcemul_and: 4813 srl t0, a0, 21-SZREG_SHFT # rs 4814 srl t1, a0, 16-SZREG_SHFT # rt 4815 srl t2, a0, 11-SZREG_SHFT # rd 4816 andi t0, t0, SZREG_MASK 4817 andi t1, t1, SZREG_MASK 4818 andi t2, t2, SZREG_MASK 4819 addu t0, a1, t0 4820 addu t1, a1, t1 4821 addu t2, a1, t2 4822 REG_PROLOGUE 4823 REG_L v0, FRAME_ZERO(t0) 4824 REG_L v1, FRAME_ZERO(t1) 4825 and v0, v0, v1 4826 REG_S v0, FRAME_ZERO(t2) 4827 REG_EPILOGUE 4828 b bcemul_done 4829 4830bcemul_or: 4831 srl t0, a0, 21-SZREG_SHFT # rs 4832 srl t1, a0, 16-SZREG_SHFT # rt 4833 srl t2, a0, 11-SZREG_SHFT # rd 4834 andi t0, t0, SZREG_MASK 4835 andi t1, t1, SZREG_MASK 4836 andi t2, t2, SZREG_MASK 4837 addu t0, a1, t0 4838 addu t1, a1, t1 4839 addu t2, a1, t2 4840 REG_PROLOGUE 4841 REG_L v0, FRAME_ZERO(t0) 4842 REG_L v1, FRAME_ZERO(t1) 4843 or v0, v0, v1 4844 REG_S v0, FRAME_ZERO(t2) 4845 REG_EPILOGUE 4846 b bcemul_done 4847 4848bcemul_xor: 4849 srl t0, a0, 21-SZREG_SHFT # rs 4850 srl t1, a0, 16-SZREG_SHFT # rt 4851 srl t2, a0, 11-SZREG_SHFT # rd 4852 andi t0, t0, SZREG_MASK 4853 andi t1, t1, SZREG_MASK 4854 andi t2, t2, SZREG_MASK 4855 addu t0, a1, t0 4856 addu t1, a1, t1 4857 addu t2, a1, t2 4858 REG_PROLOGUE 4859 REG_L v0, FRAME_ZERO(t0) 4860 REG_L v1, FRAME_ZERO(t1) 4861 xor v0, v0, v1 4862 REG_S v0, FRAME_ZERO(t2) 4863 REG_EPILOGUE 4864 b bcemul_done 4865 4866bcemul_nor: 4867 srl t0, a0, 21-SZREG_SHFT # rs 4868 srl t1, a0, 16-SZREG_SHFT # rt 4869 srl t2, a0, 11-SZREG_SHFT # rd 4870 andi t0, t0, SZREG_MASK 4871 andi t1, t1, SZREG_MASK 4872 andi t2, t2, SZREG_MASK 4873 addu t0, a1, t0 4874 addu t1, a1, t1 4875 addu t2, a1, t2 4876 REG_PROLOGUE 4877 REG_L v0, FRAME_ZERO(t0) 4878 REG_L v1, FRAME_ZERO(t1) 4879 nor v0, v0, v1 4880 REG_S v0, FRAME_ZERO(t2) 4881 REG_EPILOGUE 4882 b bcemul_done 4883 4884bcemul_slt: 4885 srl t0, a0, 21-SZREG_SHFT # rs 4886 srl t1, a0, 16-SZREG_SHFT # rt 4887 srl t2, a0, 11-SZREG_SHFT # rd 4888 andi t0, t0, SZREG_MASK 4889 andi t1, t1, SZREG_MASK 4890 andi t2, t2, SZREG_MASK 4891 addu t0, a1, t0 4892 addu t1, a1, t1 4893 addu t2, a1, t2 4894 REG_PROLOGUE 4895 REG_L v0, FRAME_ZERO(t0) 4896 REG_L v1, FRAME_ZERO(t1) 4897 slt v0, v0, v1 4898 REG_S v0, FRAME_ZERO(t2) 4899 REG_EPILOGUE 4900 b bcemul_done 4901 4902bcemul_sltu: 4903 srl t0, a0, 21-SZREG_SHFT # rs 4904 srl t1, a0, 16-SZREG_SHFT # rt 4905 srl t2, a0, 11-SZREG_SHFT # rd 4906 andi t0, t0, SZREG_MASK 4907 andi t1, t1, SZREG_MASK 4908 andi t2, t2, SZREG_MASK 4909 addu t0, a1, t0 4910 addu t1, a1, t1 4911 addu t2, a1, t2 4912 REG_PROLOGUE 4913 REG_L v0, FRAME_ZERO(t0) 4914 REG_L v1, FRAME_ZERO(t1) 4915 sltu v0, v0, v1 4916 REG_S v0, FRAME_ZERO(t2) 4917 REG_EPILOGUE 4918 sw v0, FRAME_ZERO(t2) 4919# b bcemul_done # fall through to bcemul_done 4920 4921bcemul_done: 4922/* 4923 * Succeeded to emulate instruction with no error 4924 * so compute the next PC. 4925 */ 4926 subu sp, sp, CALLFRAME_SIZ 4927 sw ra, CALLFRAME_RA(sp) 4928 sw a1, CALLFRAME_SIZ + 4(sp) 4929 4930 /* Fetch previous branch instruction */ 4931 REG_PROLOGUE 4932 REG_L a0, FRAME_EPC(a1) 4933 REG_EPILOGUE 4934 jal _C_LABEL(fuiword) 4935 4936 lw a1, CALLFRAME_SIZ + 4(sp) 4937 4938 /* Calculate branch destination */ 4939 sll t0, v0, 16 4940 sra t0, t0, 16-2 4941 REG_PROLOGUE 4942 REG_L t1, FRAME_EPC(a1) 4943 addiu t0, t0, 4 4944 addu t1, t1, t0 4945 REG_S t1, FRAME_EPC(a1) 4946 REG_EPILOGUE 4947 4948 lw ra, CALLFRAME_RA(sp) 4949 addu sp, sp, CALLFRAME_SIZ 4950 j ra 4951 4952END(bcemul_delay_slot) 4953 4954#endif 4955 4956/* 4957 * Send SIGILL, SIGFPE. 4958 * Args are same as MachEmulateFP. 4959 */ 4960LEAF(fpemul_sigill) 4961#ifdef SOFTFLOAT 4962XLEAF(bcemul_sigill) 4963#endif 4964 li t0, 0xFFFFFF00 4965 and a2, a2, t0 4966 ori a2, a2, T_RES_INST << MIPS_CR_EXC_CODE_SHIFT 4967 REG_PROLOGUE 4968 REG_S a2, FRAME_CAUSE(a1) 4969 REG_EPILOGUE 4970 4971 move a2, a0 # code = instruction 4972 lw a0, _C_LABEL(curproc) # get current process 4973 li a1, SIGILL 4974 j _C_LABEL(trapsignal) 4975END(fpemul_sigill) 4976 4977LEAF(fpemul_sigfpe) 4978 li t0, 0xFFFFFF00 4979 and a2, a2, t0 4980 ori a2, a2, T_FPE << MIPS_CR_EXC_CODE_SHIFT 4981 REG_PROLOGUE 4982 REG_S a2, FRAME_CAUSE(a1) 4983 REG_EPILOGUE 4984 4985 move a2, a0 # code = instruction 4986 lw a0, _C_LABEL(curproc) # get current process 4987 li a1, SIGFPE 4988 j _C_LABEL(trapsignal) 4989END(fpemul_sigfpe) 4990 4991#ifdef SOFTFLOAT 4992LEAF(bcemul_sigfpe) 4993 li t0, 0xFFFFFF00 4994 and a2, a2, t0 4995 ori a2, a2, T_OVFLOW << MIPS_CR_EXC_CODE_SHIFT 4996 REG_PROLOGUE 4997 REG_S a2, FRAME_CAUSE(a1) 4998 REG_EPILOGUE 4999 5000 move a2, a0 # code = instruction 5001 lw a0, _C_LABEL(curproc) # get current process 5002 li a1, SIGFPE 5003 j _C_LABEL(trapsignal) 5004END(bcemul_sigfpe) 5005#endif 5006