1 /* $OpenBSD: fp.S,v 1.9 2010/02/08 19:26:46 miod Exp $ */
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * from: @(#)fp.s 8.1 (Berkeley) 6/10/93
38 * $Id: fp.S,v 1.9 2010/02/08 19:26:46 miod Exp $
42 * Standard header stuff.
45 #include <machine/regdef.h>
46 #include <machine/asm.h>
47 #include <machine/regnum.h>
48 #include <machine/cpu.h>
53 #define DEXP_INF 0x7ff
55 #define DEXP_BIAS 1023
57 #define DEXP_MIN -1022
60 #define WEXP_MAX 30 /* maximum unbiased exponent for int */
61 #define WEXP_MIN -1 /* minimum unbiased exponent for int */
62 #define LEXP_MAX 62 /* maximum unbiased exponent for long */
63 #define LEXP_MIN -1 /* minimum unbiased exponent for long */
66 #define SIMPL_ONE 0x00800000
67 #define DIMPL_ONE 0x0010000000000000
68 #define SLEAD_ZEROS 63 - 55
69 #define DLEAD_ZEROS 63 - 52
71 #define GUARDBIT 0x0000000080000000
72 #define DGUARDBIT 0x8000000000000000
74 #define SSIGNAL_NAN 0x00400000
75 #define DSIGNAL_NAN 0x00080000
76 #define SQUIET_NAN 0x003fffff
77 #define DQUIET_NAN 0x0007ffffffffffff
78 #define INT_MIN 0x80000000
79 #define INT_MAX 0x7fffffff
80 #define LONG_MIN 0x8000000000000000
81 #define LONG_MAX 0x7fffffffffffffff
83 #define COND_UNORDERED 0x1
84 #define COND_EQUAL 0x2
86 #define COND_SIGNAL 0x8
88 /*----------------------------------------------------------------------------
92 * Emulate unimplemented floating point operations.
93 * This routine should only be called by MipsFPInterrupt()
94 * and only if this is a COP1 instruction.
96 * MipsEmulateFP(instr)
103 * Floating point registers are modified according to instruction.
105 *----------------------------------------------------------------------------
107 NON_LEAF(MipsEmulateFP, FRAMESZ(CF_SZ), ra)
108 PTR_SUB sp, sp, FRAMESZ(CF_SZ)
109 PTR_S ra, CF_RA_OFFS(sp)
111 srl v0, a0, 21 # get FMT field
112 and v0, v0, 0x1f # mask FMT field
121 b ill # illegal format
124 and v1, a0, 0x3f # mask FUNC field
125 sll v1, v1, 3 # align for table lookup
129 PTR_L a1, CI_CURPROCPADDR(a1)
130 REG_L a1, PCB_FPREGS+(32 * REGSZ)(a1)
133 cfc1 a1, FPC_CSR # get exception register
134 ld a3, (v1) # switch on FUNC & FMT
135 and a1, a1, ~FPC_EXCEPTION_UNIMPL # clear exception
142 .dword mfromc1 # sub 0 mfc1
143 .dword dmfromc1 # sub 1 dmfc1
144 .dword cfromc1 # sub 2 cfc1
145 .dword ill # sub 3 mfhc1
146 .dword mtoc1 # sub 4 mtc1
147 .dword dmtoc1 # sub 5 dmtc1
148 .dword ctoc1 # sub 6 ctc1
149 .dword ill # sub 7 mthc1
150 .dword branchc1 # sub 8 bc1
151 .dword branchc1any2 # sub 9 bc1any2
152 .dword branchc1any4 # sub 10 bc1any4
158 .dword single_op # sub 16 S
159 .dword double_op # sub 17 D
162 .dword single_fixed_op # sub 20 W
163 .dword long_fixed_op # sub 21 L
164 .dword ill # sub 22 PS
180 .dword ill # 4 (sqrt)
187 .dword floor_l_s # 11
188 .dword round_w_s # 12
189 .dword trunc_w_s # 13
191 .dword floor_w_s # 15
246 .dword ill # 4 (sqrt)
253 .dword floor_l_d # 11
254 .dword round_w_d # 12
255 .dword trunc_w_d # 13
257 .dword floor_w_d # 15
442 * Single precision subtract.
446 xor ta0, 1 # negate FT sign bit
449 * Single precision add.
454 bne t1, SEXP_INF, 1f # is FS an infinity?
455 bne ta1, SEXP_INF, result_fs_s # if FT is not inf, result=FS
456 bne t2, zero, result_fs_s # if FS is NAN, result is FS
457 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
458 bne t0, ta0, invalid_s # both infinities same sign?
459 b result_fs_s # result is in FS
461 beq ta1, SEXP_INF, result_ft_s # if FT is inf, result=FT
462 bne t1, zero, 4f # is FS a denormalized num?
463 beq t2, zero, 3f # is FS zero?
464 bne ta1, zero, 2f # is FT a denormalized num?
465 beq ta2, zero, result_fs_s # FT is zero, result=FS
471 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
472 or ta2, ta2, SIMPL_ONE # set implied one bit
475 bne ta1, zero, result_ft_s # if FT != 0, result=FT
476 bne ta2, zero, result_ft_s
477 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
478 bne v0, FPC_ROUND_RM, 1f # round to -infinity?
479 or t0, t0, ta0 # compute result sign
482 and t0, ta0 # compute result sign
485 bne ta1, zero, 2f # is FT a denormalized num?
486 beq ta2, zero, result_fs_s # FT is zero, result=FS
487 subu t1, SEXP_BIAS # unbias FS exponent
488 or t2, SIMPL_ONE # set implied one bit
492 subu t1, SEXP_BIAS # unbias FS exponent
493 or t2, SIMPL_ONE # set implied one bit
494 subu ta1, SEXP_BIAS # unbias FT exponent
495 or ta2, SIMPL_ONE # set implied one bit
497 * Perform the addition.
500 move t8, zero # no shifted bits (sticky reg)
501 beq t1, ta1, 4f # exp equal, no shift needed
502 subu v0, t1, ta1 # v0 = difference of exponents
503 move v1, v0 # v1 = abs(difference)
507 ble v1, SFRAC_BITS+2, 2f # is difference too great?
508 li t8, STICKYBIT # set the sticky bit
509 bge v0, zero, 1f # check which exp is larger
510 move t1, ta1 # result exp is FTs
511 move t2, zero # FSs fraction shifted is zero
514 move ta2, zero # FTs fraction shifted is zero
517 li t9, 32 # compute 32 - abs(exp diff)
519 bgt v0, zero, 3f # if FS > FT, shift FTs frac
520 move t1, ta1 # FT > FS, result exp is FTs
521 sll t8, t2, t9 # save bits shifted out
522 srl t2, t2, v1 # shift FSs fraction
525 sll t8, ta2, t9 # save bits shifted out
526 srl ta2, ta2, v1 # shift FTs fraction
528 bne t0, ta0, 1f # if signs differ, subtract
529 addu t2, t2, ta2 # add fractions
532 blt t2, ta2, 3f # subtract larger from smaller
533 bne t2, ta2, 2f # if same, result=0
534 move t1, zero # result=0
536 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
537 bne v0, FPC_ROUND_RM, 1f # round to -infinity?
538 or t0, t0, ta0 # compute result sign
541 and t0, t0, ta0 # compute result sign
544 sltu t9, zero, t8 # compute t2:zero - ta2:t8
546 subu t2, t2, ta2 # subtract fractions
547 subu t2, t2, t9 # subtract barrow
550 move t0, ta0 # sign of result = FTs
551 sltu t9, zero, t8 # compute ta2:zero - t2:t8
553 subu t2, ta2, t2 # subtract fractions
554 subu t2, t2, t9 # subtract barrow
558 * Double precision subtract.
562 xor ta0, ta0, 1 # negate sign bit
565 * Double precision add.
570 bne t1, DEXP_INF, 1f # is FS an infinity?
571 bne ta1, DEXP_INF, result_fs_d # if FT is not inf, result=FS
572 bne t2, zero, result_fs_d # if FS is NAN, result is FS
573 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
574 bne t0, ta0, invalid_d # both infinities same sign?
575 b result_fs_d # result is in FS
577 beq ta1, DEXP_INF, result_ft_d # if FT is inf, result=FT
578 bne t1, zero, 4f # is FS a denormalized num?
579 beq t2, zero, 3f # is FS zero?
580 bne ta1, zero, 2f # is FT a denormalized num?
581 beq ta2, zero, result_fs_d # FT is zero, result=FS
587 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
588 or ta2, ta2, DIMPL_ONE # set implied one bit
591 bne ta1, zero, result_ft_d # if FT != 0, result=FT
592 bne ta2, zero, result_ft_d
593 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
594 bne v0, FPC_ROUND_RM, 1f # round to -infinity?
595 or t0, t0, ta0 # compute result sign
598 and t0, t0, ta0 # compute result sign
601 bne ta1, zero, 2f # is FT a denormalized num?
602 beq ta2, zero, result_fs_d # FT is zero, result=FS
603 subu t1, t1, DEXP_BIAS # unbias FS exponent
604 or t2, t2, DIMPL_ONE # set implied one bit
608 subu t1, t1, DEXP_BIAS # unbias FS exponent
609 or t2, t2, DIMPL_ONE # set implied one bit
610 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
611 or ta2, ta2, DIMPL_ONE # set implied one bit
613 * Perform the addition.
616 move t8, zero # no shifted bits (sticky reg)
617 beq t1, ta1, 4f # no shift needed
618 subu v0, t1, ta1 # v0 = difference of exponents
619 move v1, v0 # v1 = abs(difference)
623 ble v1, DFRAC_BITS+2, 2f # is difference too great?
624 li t8, STICKYBIT # set the sticky bit
625 bge v0, zero, 1f # check which exp is larger
626 move t1, ta1 # result exp is FTs
627 move t2, zero # FSs fraction shifted is zero
630 move ta2, zero # FTs fraction shifted is zero
635 bge v0, zero, 3f # if FS > FT, shift FTs frac
636 move t1, ta1 # FT > FS, result exp is FTs
637 dsll t8, t2, t9 # save bits shifted out
641 dsll t8, ta2, t9 # save bits shifted out
644 bne t0, ta0, 1f # if signs differ, subtract
645 daddu t2, ta2 # add fractions
648 blt t2, ta2, 3f # subtract larger from smaller
650 move t1, zero # result=0
652 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
653 bne v0, FPC_ROUND_RM, 1f # round to -infinity?
654 or t0, t0, ta0 # compute result sign
657 and t0, t0, ta0 # compute result sign
660 sltu t9, zero, t8 # compute t2:zero - ta2:t8
662 dsubu t2, t2, ta2 # subtract fractions
663 dsubu t2, t2, t9 # subtract barrow
666 move t0, ta0 # sign of result = FTs
668 dsubu t2, ta2, t2 # subtract fractions
669 dsubu t2, t2, t9 # subtract barrow
673 * Single precision multiply.
677 xor t0, t0, ta0 # compute sign of result
679 bne t1, SEXP_INF, 2f # is FS an infinity?
680 bne t2, zero, result_fs_s # if FS is a NAN, result=FS
681 bne ta1, SEXP_INF, 1f # FS is inf, is FT an infinity?
682 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
683 b result_fs_s # result is infinity
685 bne ta1, zero, result_fs_s # inf * zero? if no, result=FS
686 bne ta2, zero, result_fs_s
687 b invalid_s # infinity * zero is invalid
689 bne ta1, SEXP_INF, 1f # FS != inf, is FT an infinity?
690 bne t1, zero, result_ft_s # zero * inf? if no, result=FT
691 bne t2, zero, result_ft_s
692 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
693 b invalid_s # zero * infinity is invalid
695 bne t1, zero, 1f # is FS zero?
696 beq t2, zero, result_fs_s # result is zero
700 subu t1, t1, SEXP_BIAS # unbias FS exponent
701 or t2, t2, SIMPL_ONE # set implied one bit
703 bne ta1, zero, 1f # is FT zero?
704 beq ta2, zero, result_ft_s # result is zero
708 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
709 or ta2, ta2, SIMPL_ONE # set implied one bit
711 addu t1, t1, ta1 # compute result exponent
712 addu t1, t1, 9 # account for binary point
713 multu t2, ta2 # multiply fractions
719 * Double precision multiply.
723 xor t0, t0, ta0 # compute sign of result
725 bne t1, DEXP_INF, 2f # is FS an infinity?
726 bne t2, zero, result_fs_d # if FS is a NAN, result=FS
727 bne ta1, DEXP_INF, 1f # FS is inf, is FT an infinity?
728 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
729 b result_fs_d # result is infinity
731 bne ta1, zero, result_fs_d # inf * zero? if no, result=FS
732 bne ta2, zero, result_fs_d
733 b invalid_d # infinity * zero is invalid
735 bne ta1, DEXP_INF, 1f # FS != inf, is FT an infinity?
736 bne t1, zero, result_ft_d # zero * inf? if no, result=FT
737 bne t2, zero, result_ft_d # if FS is a NAN, result=FS
738 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
739 b invalid_d # zero * infinity is invalid
741 bne t1, zero, 2f # is FS zero?
742 beq t2, zero, result_fs_d # result is zero
746 subu t1, t1, DEXP_BIAS # unbias FS exponent
747 or t2, t2, DIMPL_ONE # set implied one bit
749 bne ta1, zero, 2f # is FT zero?
750 beq ta2, zero, result_ft_d # result is zero
754 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
755 or ta2, ta2, DIMPL_ONE # set implied one bit
757 addu t1, t1, ta1 # compute result exponent
758 addu t1, t1, 12 # ???
759 dmultu t2, ta2 # multiply fractions
765 * Single precision divide.
769 xor t0, t0, ta0 # compute sign of result
771 bne t1, SEXP_INF, 1f # is FS an infinity?
772 bne t2, zero, result_fs_s # if FS is NAN, result is FS
773 bne ta1, SEXP_INF, result_fs_s # is FT an infinity?
774 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
775 b invalid_s # infinity/infinity is invalid
777 bne ta1, SEXP_INF, 1f # is FT an infinity?
778 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
779 move t1, zero # x / infinity is zero
783 bne t1, zero, 2f # is FS zero?
785 bne ta1, zero, result_fs_s # FS=zero, is FT zero?
786 beq ta2, zero, invalid_s # 0 / 0
787 b result_fs_s # result = zero
792 subu t1, t1, SEXP_BIAS # unbias FS exponent
793 or t2, t2, SIMPL_ONE # set implied one bit
795 bne ta1, zero, 2f # is FT zero?
797 or a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
798 and v0, a1, FPC_ENABLE_DIV0 # trap enabled?
799 bne v0, zero, fpe_trap
800 ctc1 a1, FPC_CSR # save exceptions
801 li t1, SEXP_INF # result is infinity
808 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
809 or ta2, ta2, SIMPL_ONE # set implied one bit
811 subu t1, t1, ta1 # compute exponent
812 subu t1, t1, 3 # compensate for result position
813 li v0, SFRAC_BITS+3 # number of bits to divide
814 move t8, t2 # init dividend
815 move t2, zero # init result
817 bltu t8, ta2, 3f # is dividend >= divisor?
819 subu t8, t8, ta2 # subtract divisor from dividend
820 or t2, t2, 1 # remember that we did
821 bne t8, zero, 3f # if not done, continue
822 sll t2, t2, v0 # shift result to final position
825 sll t8, t8, 1 # shift dividend
826 sll t2, t2, 1 # shift result
827 subu v0, v0, 1 # are we done?
828 bne v0, zero, 1b # no, continue
832 * Double precision divide.
836 xor t0, t0, ta0 # compute sign of result
838 bne t1, DEXP_INF, 1f # is FS an infinity?
839 bne t2, zero, result_fs_d # if FS is NAN, result is FS
840 bne ta1, DEXP_INF, result_fs_d # is FT an infinity?
841 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
842 b invalid_d # infinity/infinity is invalid
844 bne ta1, DEXP_INF, 1f # is FT an infinity?
845 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
846 move t1, zero # x / infinity is zero
850 bne t1, zero, 2f # is FS zero?
852 bne ta1, zero, result_fs_d # FS=zero, is FT zero?
853 beq ta2, zero, invalid_d # 0 / 0
854 b result_fs_d # result = zero
859 subu t1, t1, DEXP_BIAS # unbias FS exponent
860 or t2, t2, DIMPL_ONE # set implied one bit
862 bne ta1, zero, 2f # is FT zero?
864 or a1, a1, FPC_EXCEPTION_DIV0 | FPC_STICKY_DIV0
865 and v0, a1, FPC_ENABLE_DIV0 # trap enabled?
866 bne v0, zero, fpe_trap
867 ctc1 a1, FPC_CSR # Save exceptions
868 li t1, DEXP_INF # result is infinity
875 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
876 or ta2, ta2, DIMPL_ONE # set implied one bit
878 subu t1, t1, ta1 # compute exponent
879 subu t1, t1, 3 # compensate for result position
880 li v0, DFRAC_BITS+3 # number of bits to divide
881 move t8, t2 # init dividend
882 move t2, zero # init result
884 bltu t8, ta2, 3f # is dividend >= divisor?
886 dsubu t8, t8, ta2 # subtract divisor from dividend
887 or t2, t2, 1 # remember that we did
888 bne t8, zero, 3f # if not done, continue
889 dsll t2, t2, v0 # shift upper part
892 dsll t8, t8, 1 # shift dividend
893 dsll t2, t2, 1 # shift result
894 subu v0, v0, 1 # are we done?
895 bne v0, zero, 1b # no, continue
899 * Single precision absolute value.
903 move t0, zero # set sign positive
907 * Double precision absolute value.
911 move t0, zero # set sign positive
915 * Single precision move.
922 * Double precision move.
929 * Single precision negate.
933 xor t0, t0, 1 # reverse sign
937 * Double precision negate.
941 xor t0, t0, 1 # reverse sign
945 * Convert double to single.
949 bne t1, DEXP_INF, 1f # is FS an infinity?
950 li t1, SEXP_INF # convert to single
951 dsll t2, t2, 3 # convert D fraction to S
954 bne t1, zero, 2f # is FS zero?
955 beq t2, zero, result_fs_s # result=0
957 subu t1, t1, 3 # correct exp for shift below
960 subu t1, t1, DEXP_BIAS # unbias exponent
961 or t2, t2, DIMPL_ONE # add implied one bit
963 dsll t2, t2, 3 # convert D fraction to S
967 * Convert long integer to single.
973 * Convert integer to single.
978 bne t2, zero, 1f # check for zero
982 * Find out how many leading zero bits are in t2 and put in t9.
1016 * Now shift t2 the correct number of bits.
1019 subu t9, SLEAD_ZEROS # dont count leading zeros
1020 li t1, 23+32 # init exponent
1021 subu t1, t1, t9 # compute exponent
1024 blt t9, zero, 2f # if shift < 0, shift right
1026 sll t2, t2, t9 # shift left
1028 add t1, t1, SEXP_BIAS # bias exponent
1029 and t2, t2, ~SIMPL_ONE # clear implied one bit
1032 negu t9 # shift right by t9
1034 sll t8, t2, v0 # save bits shifted out
1039 * Convert single to double.
1044 bne t1, SEXP_INF, 1f # is FS an infinity?
1045 li t1, DEXP_INF # convert to double
1048 bne t1, zero, 2f # is FS denormalized or zero?
1049 beq t2, zero, result_fs_d # is FS zero?
1054 addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly
1059 * Convert long integer to double.
1065 * Convert integer to double.
1070 bne t2, zero, 1f # check for zero
1071 move t1, zero # result=0
1074 * Find out how many leading zero bits are in t2 and put in t9.
1108 * Now shift t2 the correct number of bits.
1111 subu t9, t9, DLEAD_ZEROS # dont count leading zeros
1112 li t1, DEXP_BIAS + 20 # init exponent
1113 subu t1, t1, t9 # compute exponent
1116 blt t9, zero, 2f # if shift < 0, shift right
1118 dsll t2, t2, t9 # shift left
1120 and t2, t2, ~DIMPL_ONE # clear implied one bit
1123 negu t9 # shift right by t9
1126 and t2, t2, ~DIMPL_ONE # clear implied one bit
1130 * Convert single to integer with specific rounding.
1146 * Convert single to integer.
1149 and t3, a1, FPC_ROUNDING_BITS # get rounding mode
1152 bne t1, SEXP_INF, 1f # is FS an infinity?
1153 bne t2, zero, invalid_w # invalid conversion
1155 bne t1, zero, 1f # is FS zero?
1156 beq t2, zero, result_fs_w # result is zero
1157 move t2, zero # result is an inexact zero
1160 subu t1, t1, SEXP_BIAS # unbias exponent
1161 or t2, t2, SIMPL_ONE # add implied one bit
1162 dsll t2, t2, DFRAC_BITS - SFRAC_BITS # convert S fraction to D
1166 * Convert double to integer with specific rounding.
1182 * Convert double to integer.
1185 and t3, a1, FPC_ROUNDING_BITS # get rounding mode
1188 bne t1, DEXP_INF, 1f # is FS an infinity?
1189 bne t2, zero, invalid_w # invalid conversion
1191 bne t1, zero, 2f # is FS zero?
1192 beq t2, zero, result_fs_w # result is zero
1193 move t2, zero # result is an inexact zero
1196 subu t1, t1, DEXP_BIAS # unbias exponent
1197 or t2, t2, DIMPL_ONE # add implied one bit
1199 blt t1, WEXP_MIN, underflow_w # is exponent too small?
1201 bgt t1, v0, overflow_w # is exponent too large?
1202 bne t1, v0, 1f # special check for INT_MIN
1203 beq t0, zero, overflow_w # if positive, overflow
1204 bne t2, DIMPL_ONE, overflow_w
1205 li t2, INT_MIN # result is INT_MIN
1208 subu v0, t1, 20 # compute amount to shift
1209 beq v0, zero, 2f # is shift needed?
1211 blt v0, zero, 1f # if shift < 0, shift right
1212 subu v1, v1, v0 # shift left
1216 negu v0 # shift right by v0
1218 dsll t8, t2, v1 # save bits shifted out
1219 sltu t8, zero, t8 # dont lose any ones
1222 * round (t0 is sign, t2:63-32 is integer part, t2:31-0 is fractional part).
1225 beq t3, FPC_ROUND_RN, 3f # round to nearest
1226 beq t3, FPC_ROUND_RZ, 5f # round to zero (truncate)
1227 beq t3, FPC_ROUND_RP, 1f # round to +infinity
1228 beq t0, zero, 5f # if sign is positive, truncate
1231 bne t0, zero, 5f # if sign is negative, truncate
1233 daddu t2, t2, GUARDBIT # add in fractional
1234 blt t2, zero, overflow_w # overflow?
1237 daddu t2, t2, GUARDBIT # add in fractional
1238 blt t2, zero, overflow_w # overflow?
1240 bne v0, zero, 5f # if rounded remainder is zero
1241 and t2, 0xfffffffe00000000 # clear LSB (round to nearest)
1243 beq t0, zero, 1f # result positive?
1244 negu t2 # convert to negative integer
1246 dsll v0, 32 # save fraction
1247 dsrl t2, 32 # shift out fractional part
1248 beq v0, zero, result_fs_w # is result exact?
1250 * Handle inexact exception.
1253 or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1254 and v0, a1, FPC_ENABLE_INEXACT
1255 bne v0, zero, fpe_trap
1256 ctc1 a1, FPC_CSR # save exceptions
1260 * Conversions to integer which overflow will trap (if enabled),
1261 * or generate an inexact trap (if enabled),
1262 * or generate an invalid exception.
1265 or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1266 and v0, a1, FPC_ENABLE_OVERFLOW
1267 bne v0, zero, fpe_trap
1268 and v0, a1, FPC_ENABLE_INEXACT
1269 bne v0, zero, inexact_w # inexact traps enabled?
1273 * Conversions to integer which underflow will trap (if enabled),
1274 * or generate an inexact trap (if enabled),
1275 * or generate an invalid exception.
1278 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1279 and v0, a1, FPC_ENABLE_UNDERFLOW
1280 bne v0, zero, fpe_trap
1281 and v0, a1, FPC_ENABLE_INEXACT
1282 bne v0, zero, inexact_w # inexact traps enabled?
1286 * Convert single to long integer with specific rounding.
1302 * Convert single to long integer.
1305 and t3, a1, FPC_ROUNDING_BITS # get rounding mode
1308 bne t1, SEXP_INF, 1f # is FS an infinity?
1309 bne t2, zero, invalid_l # invalid conversion
1311 bne t1, zero, 1f # is FS zero?
1312 beq t2, zero, result_fs_l # result is zero
1313 move t2, zero # result is an inexact zero
1316 subu t1, t1, SEXP_BIAS # unbias exponent
1317 or t2, t2, SIMPL_ONE # add implied one bit
1318 dsll t2, t2, DFRAC_BITS - SFRAC_BITS # convert S fraction to D
1322 * Convert double to long integer with specific rounding.
1338 * Convert double to long integer.
1341 and t3, a1, FPC_ROUNDING_BITS # get rounding mode
1344 bne t1, DEXP_INF, 1f # is FS an infinity?
1345 bne t2, zero, invalid_l # invalid conversion
1347 bne t1, zero, 2f # is FS zero?
1348 beq t2, zero, result_fs_l # result is zero
1349 move t2, zero # result is an inexact zero
1352 subu t1, t1, DEXP_BIAS # unbias exponent
1353 or t2, t2, DIMPL_ONE # add implied one bit
1355 blt t1, LEXP_MIN, underflow_l # is exponent too small?
1357 bgt t1, v0, overflow_l # is exponent too large?
1358 bne t1, v0, 1f # special check for LONG_MIN
1359 beq t0, zero, overflow_l # if positive, overflow
1360 bne t2, DIMPL_ONE, overflow_l
1361 dli t2, LONG_MIN # result is LONG_MIN
1364 subu v0, t1, DFRAC_BITS # compute amount to shift
1365 beq v0, zero, 2f # is shift needed?
1367 blt v0, zero, 1f # if shift < 0, shift right
1368 subu v1, v1, v0 # shift left
1372 negu v0 # shift right by v0
1374 dsll t8, t2, v1 # save bits shifted out
1375 sltu t8, zero, t8 # dont lose any ones
1378 * round (t0 is sign, t2 is integer part).
1381 beq t3, FPC_ROUND_RN, 3f # round to nearest
1382 beq t3, FPC_ROUND_RZ, 5f # round to zero (truncate)
1383 beq t3, FPC_ROUND_RP, 1f # round to +infinity
1384 beq t0, zero, 5f # if sign is positive, truncate
1387 bne t0, zero, 5f # if sign is negative, truncate
1389 daddu t2, t2, DGUARDBIT # add in fractional
1390 blt t2, zero, overflow_l # overflow?
1393 daddu t2, t2, DGUARDBIT # add in fractional
1394 blt t2, zero, overflow_l # overflow?
1396 bne v0, zero, 5f # if rounded remainder is zero
1397 and t2, 0xe000000000000000 # clear LSB (round to nearest)
1399 beq t0, zero, 1f # result positive?
1400 negu t2 # convert to negative integer
1405 * Handle inexact exception.
1408 or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1409 and v0, a1, FPC_ENABLE_INEXACT
1410 bne v0, zero, fpe_trap
1411 ctc1 a1, FPC_CSR # save exceptions
1415 * Conversions to integer which overflow will trap (if enabled),
1416 * or generate an inexact trap (if enabled),
1417 * or generate an invalid exception.
1420 or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1421 and v0, a1, FPC_ENABLE_OVERFLOW
1422 bne v0, zero, fpe_trap
1423 and v0, a1, FPC_ENABLE_INEXACT
1424 bne v0, zero, inexact_l # inexact traps enabled?
1428 * Conversions to integer which underflow will trap (if enabled),
1429 * or generate an inexact trap (if enabled),
1430 * or generate an invalid exception.
1433 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1434 and v0, a1, FPC_ENABLE_UNDERFLOW
1435 bne v0, zero, fpe_trap
1436 and v0, a1, FPC_ENABLE_INEXACT
1437 bne v0, zero, inexact_l # inexact traps enabled?
1445 bne t1, SEXP_INF, 1f # is FS an infinity?
1446 bne t2, zero, unordered # FS is a NAN
1448 bne ta1, SEXP_INF, 2f # is FT an infinity?
1449 bne ta2, zero, unordered # FT is a NAN
1451 sll t1, t1, SFRAC_BITS # reassemble exp & frac
1453 sll ta1, ta1, SFRAC_BITS # reassemble exp & frac
1455 beq t0, zero, 1f # is FS positive?
1458 beq ta0, zero, 1f # is FT positive?
1462 blt t1, ta1, test_cond # is FS < FT?
1464 beq t1, ta1, test_cond # is FS == FT?
1465 move v0, zero # FS > FT
1473 bne t1, DEXP_INF, 1f # is FS an infinity?
1474 bne t2, zero, unordered # FS is a NAN
1476 bne ta1, DEXP_INF, 2f # is FT an infinity?
1477 bne ta2, zero, unordered # FT is a NAN
1479 dsll t1, t1, DFRAC_BITS # reassemble exp & frac
1481 dsll ta1, ta1, DFRAC_BITS # reassemble exp & frac
1483 beq t0, zero, 1f # is FS positive?
1484 dnegu t1 # negate t1
1486 beq ta0, zero, 1f # is FT positive?
1490 blt t1, ta1, test_cond # is FS(MSW) < FT(MSW)?
1492 beq t1, ta1, test_cond # is FS(LSW) == FT(LSW)?
1493 move v0, zero # FS > FT
1495 and v0, v0, a0 # condition match instruction?
1498 and a1, a1, ~FPC_COND_BIT # clear condition bit
1501 or a1, a1, FPC_COND_BIT # set condition bit
1503 ctc1 a1, FPC_CSR # save condition bit
1507 and v0, a0, COND_UNORDERED # this cmp match unordered?
1509 and a1, a1, ~FPC_COND_BIT # clear condition bit
1512 or a1, a1, FPC_COND_BIT # set condition bit
1514 and v0, a0, COND_SIGNAL
1515 beq v0, zero, 1f # is this a signaling cmp?
1516 or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
1517 and v0, a1, FPC_ENABLE_INVALID
1518 bne v0, zero, fpe_trap
1520 ctc1 a1, FPC_CSR # save condition bit
1524 * Determine the amount to shift the fraction in order to restore the
1525 * normalized position. After that, round and handle exceptions.
1529 move t9, zero # t9 = num of leading zeros
1558 * Now shift t2,t8 the correct number of bits.
1561 subu t9, t9, SLEAD_ZEROS # dont count leading zeros
1562 subu t1, t1, t9 # adjust the exponent
1563 beq t9, zero, norm_noshift_s
1565 blt t9, zero, 1f # if shift < 0, shift right
1567 sll t2, t2, t9 # shift t2,t8 left
1568 srl v0, t8, v1 # save bits shifted out
1573 negu t9 # shift t2,t8 right by t9
1575 sll v0, t8, v1 # save bits shifted out
1576 sltu v0, zero, v0 # be sure to save any one bits
1579 sll v0, t2, v1 # save bits shifted out
1583 move ta1, t1 # save unrounded exponent
1584 move ta2, t2 # save unrounded fraction
1585 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1586 beq v0, FPC_ROUND_RN, 3f # round to nearest
1587 beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
1588 beq v0, FPC_ROUND_RP, 1f # round to +infinity
1589 beq t0, zero, 5f # if sign is positive, truncate
1592 bne t0, zero, 5f # if sign is negative, truncate
1594 beq t8, zero, 5f # if exact, continue
1595 addu t2, t2, 1 # add rounding bit
1596 bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent?
1597 addu t1, t1, 1 # adjust exponent
1598 srl t2, t2, 1 # renormalize fraction
1601 li v0, GUARDBIT # load guard bit for rounding
1602 addu v0, v0, t8 # add remainder
1603 sltu v1, v0, t8 # compute carry out
1604 beq v1, zero, 4f # if no carry, continue
1605 addu t2, t2, 1 # add carry to result
1606 bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent?
1607 addu t1, t1, 1 # adjust exponent
1608 srl t2, t2, 1 # renormalize fraction
1610 bne v0, zero, 5f # if rounded remainder is zero
1611 and t2, t2, ~1 # clear LSB (round to nearest)
1613 bgt t1, SEXP_MAX, overflow_s # overflow?
1614 blt t1, SEXP_MIN, underflow_s # underflow?
1615 bne t8, zero, inexact_s # is result inexact?
1616 addu t1, t1, SEXP_BIAS # bias exponent
1617 and t2, t2, ~SIMPL_ONE # clear implied one bit
1621 * Handle inexact exception.
1624 addu t1, t1, SEXP_BIAS # bias exponent
1625 and t2, t2, ~SIMPL_ONE # clear implied one bit
1627 jal set_fd_s # save result
1628 or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1629 and v0, a1, FPC_ENABLE_INEXACT
1630 bne v0, zero, fpe_trap
1631 ctc1 a1, FPC_CSR # save exceptions
1635 * Overflow will trap (if enabled),
1636 * or generate an inexact trap (if enabled),
1637 * or generate an infinity.
1640 or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1641 and v0, a1, FPC_ENABLE_OVERFLOW
1643 subu t1, t1, 192 # bias exponent
1644 and t2, t2, ~SIMPL_ONE # clear implied one bit
1645 jal set_fd_s # save result
1648 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1649 beq v0, FPC_ROUND_RN, 3f # round to nearest
1650 beq v0, FPC_ROUND_RZ, 1f # round to zero (truncate)
1651 beq v0, FPC_ROUND_RP, 2f # round to +infinity
1654 li t1, SEXP_MAX # result is max finite
1660 li t1, SEXP_MAX + 1 # result is infinity
1665 * In this implementation, "tininess" is detected "after rounding" and
1666 * "loss of accuracy" is detected as "an inexact result".
1669 and v0, a1, FPC_ENABLE_UNDERFLOW
1672 * Underflow is enabled so compute the result and trap.
1674 addu t1, t1, 192 # bias exponent
1675 and t2, t2, ~SIMPL_ONE # clear implied one bit
1676 jal set_fd_s # save result
1677 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1680 * Underflow is not enabled so compute the result,
1681 * signal inexact result (if it is) and trap (if enabled).
1684 move t1, ta1 # get unrounded exponent
1685 move t2, ta2 # get unrounded fraction
1686 li t9, SEXP_MIN # compute shift amount
1687 subu t9, t9, t1 # shift t2,t8 right by t9
1688 blt t9, SFRAC_BITS+2, 3f # shift all the bits out?
1689 move t1, zero # result is inexact zero
1691 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1693 * Now round the zero result.
1694 * Only need to worry about rounding to +- infinity when the sign matches.
1696 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1697 beq v0, FPC_ROUND_RN, inexact_nobias_s # round to nearest
1698 beq v0, FPC_ROUND_RZ, inexact_nobias_s # round to zero
1699 beq v0, FPC_ROUND_RP, 1f # round to +infinity
1700 beq t0, zero, inexact_nobias_s # if sign is positive, truncate
1703 bne t0, zero, inexact_nobias_s # if sign is negative, truncate
1705 addu t2, t2, 1 # add rounding bit
1710 sltu v0, zero, t8 # be sure to save any one bits
1711 sll t8, t2, v1 # save bits shifted out
1712 or t8, t8, v0 # include sticky bits
1715 * Now round the denormalized result.
1717 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1718 beq v0, FPC_ROUND_RN, 3f # round to nearest
1719 beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
1720 beq v0, FPC_ROUND_RP, 1f # round to +infinity
1721 beq t0, zero, 5f # if sign is positive, truncate
1724 bne t0, zero, 5f # if sign is negative, truncate
1726 beq t8, zero, 5f # if exact, continue
1727 addu t2, t2, 1 # add rounding bit
1730 li v0, GUARDBIT # load guard bit for rounding
1731 addu v0, v0, t8 # add remainder
1732 sltu v1, v0, t8 # compute carry out
1733 beq v1, zero, 4f # if no carry, continue
1734 addu t2, t2, 1 # add carry to result
1736 bne v0, zero, 5f # if rounded remainder is zero
1737 and t2, t2, ~1 # clear LSB (round to nearest)
1739 move t1, zero # denorm or zero exponent
1740 jal set_fd_s # save result
1741 beq t8, zero, done # check for exact result
1742 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1743 or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1744 and v0, a1, FPC_ENABLE_INEXACT
1745 bne v0, zero, fpe_trap
1746 ctc1 a1, FPC_CSR # save exceptions
1750 * Determine the amount to shift the fraction in order to restore the
1751 * normalized position. After that, round and handle exceptions.
1755 move t9, zero # t9 = num of leading zeros
1785 * Now shift t2,t8 the correct number of bits.
1788 subu t9, t9, DLEAD_ZEROS # dont count leading zeros
1789 subu t1, t1, t9 # adjust the exponent
1790 beq t9, zero, norm_noshift_d
1792 blt t9, zero, 2f # if shift < 0, shift right
1794 dsll t2, t2, t9 # shift left by t9
1795 dsrl v0, t8, v1 # save bits shifted out
1800 negu t9 # shift right by t9
1801 subu v1, v1, t9 # (known to be < 32 bits)
1802 dsll v0, t8, v1 # save bits shifted out
1803 sltu v0, zero, v0 # be sure to save any one bits
1806 dsll v0, t2, v1 # save bits shifted out
1810 move ta1, t1 # save unrounded exponent
1811 move ta2, t2 # save unrounded fraction (MS)
1812 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1813 beq v0, FPC_ROUND_RN, 3f # round to nearest
1814 beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
1815 beq v0, FPC_ROUND_RP, 1f # round to +infinity
1816 beq t0, zero, 5f # if sign is positive, truncate
1819 bne t0, zero, 5f # if sign is negative, truncate
1821 beq t8, zero, 5f # if exact, continue
1822 daddu t2, t2, 1 # add rounding bit
1823 bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent?
1824 addu t1, t1, 1 # adjust exponent
1825 dsrl t2, t2, 1 # renormalize fraction
1828 dli v0, DGUARDBIT # load guard bit for rounding
1829 addu v0, v0, t8 # add remainder
1830 sltu v1, v0, t8 # compute carry out
1831 beq v1, zero, 4f # branch if no carry
1832 daddu t2, t2, 1 # add carry to result
1833 bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent?
1834 addu t1, t1, 1 # adjust exponent
1835 srl t2, t2, 1 # renormalize fraction
1837 bne v0, zero, 5f # if rounded remainder is zero
1838 and t2, t2, ~1 # clear LSB (round to nearest)
1840 bgt t1, DEXP_MAX, overflow_d # overflow?
1841 blt t1, DEXP_MIN, underflow_d # underflow?
1842 bne t8, zero, inexact_d # is result inexact?
1843 addu t1, t1, DEXP_BIAS # bias exponent
1844 and t2, t2, ~DIMPL_ONE # clear implied one bit
1848 * Handle inexact exception.
1851 addu t1, t1, DEXP_BIAS # bias exponent
1852 and t2, t2, ~DIMPL_ONE # clear implied one bit
1854 jal set_fd_d # save result
1855 or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1856 and v0, a1, FPC_ENABLE_INEXACT
1857 bne v0, zero, fpe_trap
1858 ctc1 a1, FPC_CSR # save exceptions
1862 * Overflow will trap (if enabled),
1863 * or generate an inexact trap (if enabled),
1864 * or generate an infinity.
1867 or a1, a1, FPC_EXCEPTION_OVERFLOW | FPC_STICKY_OVERFLOW
1868 and v0, a1, FPC_ENABLE_OVERFLOW
1870 subu t1, t1, 1536 # bias exponent
1871 and t2, t2, ~DIMPL_ONE # clear implied one bit
1872 jal set_fd_d # save result
1875 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1876 beq v0, FPC_ROUND_RN, 3f # round to nearest
1877 beq v0, FPC_ROUND_RZ, 1f # round to zero (truncate)
1878 beq v0, FPC_ROUND_RP, 2f # round to +infinity
1881 li t1, DEXP_MAX # result is max finite
1882 dli t2, 0x000fffffffffffff
1887 li t1, DEXP_MAX + 1 # result is infinity
1892 * In this implementation, "tininess" is detected "after rounding" and
1893 * "loss of accuracy" is detected as "an inexact result".
1896 and v0, a1, FPC_ENABLE_UNDERFLOW
1899 * Underflow is enabled so compute the result and trap.
1901 addu t1, t1, 1536 # bias exponent
1902 and t2, t2, ~DIMPL_ONE # clear implied one bit
1903 jal set_fd_d # save result
1904 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1907 * Underflow is not enabled so compute the result,
1908 * signal inexact result (if it is) and trap (if enabled).
1911 move t1, ta1 # get unrounded exponent
1912 move t2, ta2 # get unrounded fraction (MS)
1913 li t9, DEXP_MIN # compute shift amount
1914 subu t9, t9, t1 # shift t2,t8 right by t9
1915 blt t9, DFRAC_BITS+2, 3f # shift all the bits out?
1916 move t1, zero # result is inexact zero
1918 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1920 * Now round the zero result.
1921 * Only need to worry about rounding to +- infinity when the sign matches.
1923 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1924 beq v0, FPC_ROUND_RN, inexact_nobias_d # round to nearest
1925 beq v0, FPC_ROUND_RZ, inexact_nobias_d # round to zero
1926 beq v0, FPC_ROUND_RP, 1f # round to +infinity
1927 beq t0, zero, inexact_nobias_d # if sign is positive, truncate
1930 bne t0, zero, inexact_nobias_d # if sign is negative, truncate
1932 daddu t2, t2, 1 # add rounding bit
1937 sltu v0, zero, t8 # be sure to save any one bits
1938 dsll t8, t2, v1 # save bits shifted out
1939 or t8, t8, v0 # include sticky bits
1942 * Now round the denormalized result.
1944 and v0, a1, FPC_ROUNDING_BITS # get rounding mode
1945 beq v0, FPC_ROUND_RN, 3f # round to nearest
1946 beq v0, FPC_ROUND_RZ, 5f # round to zero (truncate)
1947 beq v0, FPC_ROUND_RP, 1f # round to +infinity
1948 beq t0, zero, 5f # if sign is positive, truncate
1951 bne t0, zero, 5f # if sign is negative, truncate
1953 beq t8, zero, 5f # if exact, continue
1954 daddu t2, t2, 1 # add rounding bit
1957 dli v0, DGUARDBIT # load guard bit for rounding
1958 daddu v0, v0, t8 # add remainder
1959 sltu v1, v0, t8 # compute carry out
1960 beq v1, zero, 4f # if no carry, continue
1961 daddu t2, t2, 1 # add carry
1963 bne v0, zero, 5f # if rounded remainder is zero
1964 and t2, t2, ~1 # clear LSB (round to nearest)
1966 move t1, zero # denorm or zero exponent
1967 jal set_fd_d # save result
1968 beq t8, zero, done # check for exact result
1969 or a1, a1, FPC_EXCEPTION_UNDERFLOW | FPC_STICKY_UNDERFLOW
1970 or a1, a1, FPC_EXCEPTION_INEXACT | FPC_STICKY_INEXACT
1971 and v0, a1, FPC_ENABLE_INEXACT
1972 bne v0, zero, fpe_trap
1973 ctc1 a1, FPC_CSR # save exceptions
1977 * Signal an invalid operation if the trap is enabled; otherwise,
1978 * the result is a quiet NAN.
1980 invalid_s: # trap invalid operation
1981 or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
1982 and v0, a1, FPC_ENABLE_INVALID
1983 bne v0, zero, fpe_trap
1984 ctc1 a1, FPC_CSR # save exceptions
1985 move t0, zero # result is a quiet NAN
1988 jal set_fd_s # save result (in t0,t1,t2)
1992 * Signal an invalid operation if the trap is enabled; otherwise,
1993 * the result is a quiet NAN.
1995 invalid_d: # trap invalid operation
1996 or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
1997 and v0, a1, FPC_ENABLE_INVALID
1998 bne v0, zero, fpe_trap
1999 ctc1 a1, FPC_CSR # save exceptions
2000 move t0, zero # result is a quiet NAN
2003 jal set_fd_d # save result (in t0,t1,t2)
2007 * Signal an invalid operation if the trap is enabled; otherwise,
2008 * the result is INT_MAX or INT_MIN.
2010 invalid_w: # trap invalid operation
2011 or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
2012 and v0, a1, FPC_ENABLE_INVALID
2013 bne v0, zero, fpe_trap
2014 ctc1 a1, FPC_CSR # save exceptions
2016 li t2, INT_MAX # result is INT_MAX
2019 li t2, INT_MIN # result is INT_MIN
2023 * Signal an invalid operation if the trap is enabled; otherwise,
2024 * the result is LONG_MAX or LONG_MIN.
2026 invalid_l: # trap invalid operation
2027 or a1, a1, FPC_EXCEPTION_INVALID | FPC_STICKY_INVALID
2028 and v0, a1, FPC_ENABLE_INVALID
2029 bne v0, zero, fpe_trap
2030 ctc1 a1, FPC_CSR # save exceptions
2032 dli t2, LONG_MAX # result is INT_MAX
2035 dli t2, LONG_MIN # result is INT_MIN
2039 * Trap if the hardware should have handled this case.
2042 move a2, a1 # code = FP CSR
2043 ctc1 a1, FPC_CSR # save exceptions
2048 * Send an illegal instruction signal to the current process.
2051 ctc1 a1, FPC_CSR # save exceptions
2052 move a2, a0 # code = FP instruction
2057 move t0, ta0 # result is FT
2060 result_fs_s: # result is FS
2061 jal set_fd_s # save result (in t0,t1,t2)
2065 jal set_fd_word # save result (in t2)
2070 jal set_fd_dword # save result (in t0)
2074 move t0, ta0 # result is FT
2077 result_fs_d: # result is FS
2078 jal set_fd_d # save result (in t0,t1,t2)
2083 PTR_L ra, CF_RA_OFFS(sp)
2084 PTR_ADD sp, sp, FRAMESZ(CF_SZ)
2088 /*----------------------------------------------------------------------------
2091 * Read (integer) the FS register (bits 15-11).
2092 * This is an internal routine used by MipsEmulateFP only.
2095 * t0 contains the sign
2096 * t2 contains the fraction
2098 *----------------------------------------------------------------------------
2100 #define GET_FS_INT(n) \
2102 .dword get_fs_int_ ## n; \
2109 srl a3, a0, 11 - 3 # get FS field
2110 and a3, a3, 0x1f << 3 # mask FS field
2111 ld a3, get_fs_int_tbl(a3) # switch on register number
2152 srl t0, t2, 31 # init the sign bit
2161 /*----------------------------------------------------------------------------
2164 * Read (long integer) the FS register (bits 15-11).
2165 * This is an internal routine used by MipsEmulateFP only.
2168 * t0 contains the sign
2169 * t2 contains the fraction
2171 *----------------------------------------------------------------------------
2173 #define GET_FS_LONG(n) \
2175 .dword get_fs_long_ ## n; \
2177 get_fs_long_ ## n: \
2181 LEAF(get_fs_long, 0)
2182 srl a3, a0, 11 - 3 # get FS field
2183 and a3, a3, 0x1f << 3 # mask FS field
2184 ld a3, get_fs_long_tbl(a3) # switch on register number
2225 dsrl t0, t2, 63 # init the sign bit
2232 /*----------------------------------------------------------------------------
2235 * Read (single precision) the FT register (bits 20-16) and
2236 * the FS register (bits 15-11) and break up into fields.
2237 * This is an internal routine used by MipsEmulateFP only.
2240 * t0 contains the FS sign
2241 * t1 contains the FS (biased) exponent
2242 * t2 contains the FS fraction
2243 * ta0 contains the FT sign
2244 * ta1 contains the FT (biased) exponent
2245 * ta2 contains the FT fraction
2247 *----------------------------------------------------------------------------
2249 #define GET_FT_S(n) \
2251 .dword get_ft_s_ ## n; \
2257 LEAF(get_ft_fs_s, 0)
2258 srl a3, a0, 16 - 3 # get FT field
2259 and a3, a3, 0x1f << 3 # mask FT field
2260 ld a3, get_ft_s_tbl(a3) # switch on register number
2301 srl ta1, ta0, SFRAC_BITS # get exponent
2303 and ta2, ta0, 0x7FFFFF # get fraction
2304 srl ta0, ta0, 31 # get sign
2305 bne ta1, SEXP_INF, 1f # is it a signaling NAN?
2306 and v0, ta2, SSIGNAL_NAN
2307 bne v0, zero, invalid_s
2309 /* fall through to get FS */
2311 /*----------------------------------------------------------------------------
2314 * Read (single precision) the FS register (bits 15-11) and
2315 * break up into fields.
2316 * This is an internal routine used by MipsEmulateFP only.
2319 * t0 contains the sign
2320 * t1 contains the (biased) exponent
2321 * t2 contains the fraction
2323 *----------------------------------------------------------------------------
2325 #define GET_FS_S(n) \
2327 .dword get_fs_s_ ## n; \
2334 srl a3, a0, 11 - 3 # get FS field
2335 and a3, a3, 0x1f << 3 # mask FS field
2336 ld a3, get_fs_s_tbl(a3) # switch on register number
2377 srl t1, t0, SFRAC_BITS # get exponent
2379 and t2, t0, 0x7FFFFF # get fraction
2380 srl t0, t0, 31 # get sign
2381 bne t1, SEXP_INF, 1f # is it a signaling NAN?
2382 and v0, t2, SSIGNAL_NAN
2383 bne v0, zero, invalid_s
2388 /*----------------------------------------------------------------------------
2391 * Read (double precision) the FT register (bits 20-16) and
2392 * the FS register (bits 15-11) and break up into fields.
2393 * This is an internal routine used by MipsEmulateFP only.
2396 * t0 contains the FS sign
2397 * t1 contains the FS (biased) exponent
2398 * t2 contains the FS fraction
2399 * ta0 contains the FT sign
2400 * ta1 contains the FT (biased) exponent
2401 * ta2 contains the FT fraction
2403 *----------------------------------------------------------------------------
2405 #define GET_FT_FS_D(n) \
2407 .dword get_ft_fs_d_ ## n; \
2409 get_ft_fs_d_ ## n: \
2410 dmfc1 ta2, $ ## n; \
2413 LEAF(get_ft_fs_d, 0)
2414 srl a3, a0, 16 - 3 # get FT field
2415 and a3, a3, 0x1f << 3 # mask FT field
2416 ld a3, get_ft_d_tbl(a3) # switch on register number
2457 dsrl ta0, ta2, 63 # get sign
2458 dsrl ta1, ta2, DFRAC_BITS # get exponent
2461 dsrl ta2, 12 # get fraction
2462 bne ta1, DEXP_INF, 1f # is it a signaling NAN?
2463 and v0, ta2, DSIGNAL_NAN
2464 bne v0, zero, invalid_d
2466 /* fall through to get FS */
2468 /*----------------------------------------------------------------------------
2471 * Read (double precision) the FS register (bits 15-11) and
2472 * break up into fields.
2473 * This is an internal routine used by MipsEmulateFP only.
2476 * t0 contains the sign
2477 * t1 contains the (biased) exponent
2478 * t2 contains the fraction
2480 *----------------------------------------------------------------------------
2482 #define GET_FS_D(n) \
2484 .dword get_fs_d_ ## n; \
2491 srl a3, a0, 11 - 3 # get FS field
2492 and a3, a3, 0x1f << 3 # mask FS field
2493 ld a3, get_fs_d_tbl(a3) # switch on register number
2534 dsrl t0, t2, 63 # get sign
2535 dsrl t1, t2, DFRAC_BITS # get exponent
2538 dsrl t2, 12 # get fraction
2539 bne t1, DEXP_INF, 1f # is it a signaling NAN?
2540 and v0, t2, DSIGNAL_NAN
2541 bne v0, zero, invalid_d
2546 /*----------------------------------------------------------------------------
2549 * Read (single precision) the FS register (bits 15-11) and
2550 * the FT register (bits 20-16) and break up into fields.
2551 * This is an internal routine used by MipsEmulateFP only.
2554 * t0 contains the sign
2555 * t1 contains the (biased) exponent
2556 * t2 contains the fraction
2557 * ta0 contains the sign
2558 * ta1 contains the (biased) exponent
2559 * ta2 contains the fraction
2561 *----------------------------------------------------------------------------
2563 #define CMP_FS_S(n) \
2565 .dword cmp_fs_s_ ## n; \
2572 srl a3, a0, 11 - 3 # get FS field
2573 and a3, a3, 0x1f << 3 # mask FS field
2574 ld a3, cmp_fs_s_tbl(a3) # switch on register number
2615 srl t1, t0, SFRAC_BITS # get exponent
2617 and t2, t0, 0x7FFFFF # get fraction
2618 srl t0, t0, 31 # get sign
2620 #define CMP_FT_S(n) \
2622 .dword cmp_ft_s_ ## n; \
2628 srl a3, a0, 16 - 3 # get FT field
2629 and a3, a3, 0x1f << 3 # mask FT field
2630 ld a3, cmp_ft_s_tbl(a3) # switch on register number
2670 srl ta1, ta0, SFRAC_BITS # get exponent
2672 and ta2, ta0, 0x7FFFFF # get fraction
2673 srl ta0, ta0, 31 # get sign
2677 /*----------------------------------------------------------------------------
2680 * Read (double precision) the FS register (bits 15-11) and
2681 * the FT register (bits 20-16) and break up into fields.
2682 * This is an internal routine used by MipsEmulateFP only.
2685 * t0 contains the sign
2686 * t1 contains the (biased) exponent
2687 * t2 contains the fraction
2688 * ta0 contains the sign
2689 * ta1 contains the (biased) exponent
2690 * ta2 contains the fraction
2692 *----------------------------------------------------------------------------
2694 #define CMP_FS_D(n) \
2696 .dword cmp_fs_d_ ## n; \
2703 srl a3, a0, 11 - 3 # get FS field
2704 and a3, a3, 0x1f << 3 # mask FS field
2705 ld a3, cmp_fs_d_tbl(a3) # switch on register number
2746 dsrl t0, t2, 63 # get sign
2747 dsrl t1, t2, DFRAC_BITS # get exponent
2750 dsrl t2, 12 # get fraction
2752 #define CMP_FT_D(n) \
2754 .dword cmp_ft_d_ ## n; \
2757 dmfc1 ta2, $ ## n; \
2760 srl a3, a0, 16 - 3 # get FT field
2761 and a3, a3, 0x1f << 3 # mask FT field
2762 ld a3, cmp_ft_d_tbl(a3) # switch on register number
2803 dsrl ta0, ta2, 63 # get sign
2804 dsrl ta1, ta2, DFRAC_BITS # get exponent
2807 dsrl ta2, 12 # get fraction
2811 /*----------------------------------------------------------------------------
2814 * Write (single precision) the FD register (bits 10-6).
2815 * This is an internal routine used by MipsEmulateFP only.
2818 * a0 contains the FP instruction
2819 * t0 contains the sign
2820 * t1 contains the (biased) exponent
2821 * t2 contains the fraction
2825 * Write (integer) the FD register (bits 10-6).
2826 * This is an internal routine used by MipsEmulateFP only.
2829 * a0 contains the FP instruction
2830 * t2 contains the integer
2832 *----------------------------------------------------------------------------
2834 #define SET_FD_S(n) \
2836 .dword set_fd_s_ ## n; \
2843 sll t0, t0, 31 # position sign
2844 sll t1, t1, SFRAC_BITS # position exponent
2848 srl a3, a0, 6 - 3 # get FD field
2849 and a3, a3, 0x1f << 3 # mask FT field
2850 ld a3, set_fd_s_tbl(a3) # switch on register number
2892 /*----------------------------------------------------------------------------
2895 * Write (double precision) the FT register (bits 10-6).
2896 * This is an internal routine used by MipsEmulateFP only.
2899 * a0 contains the FP instruction
2900 * t0 contains the sign
2901 * t1 contains the (biased) exponent
2902 * t2 contains the fraction
2904 *----------------------------------------------------------------------------
2906 #define SET_FD_D(n) \
2908 .dword set_fd_d_ ## n; \
2915 dsll t0, 63 # set sign
2916 dsll t1, t1, DFRAC_BITS # set exponent
2918 or t0, t0, t2 # set fraction
2920 srl a3, a0, 6 - 3 # get FD field
2921 and a3, a3, 0x1f << 3 # mask FD field
2922 ld a3, set_fd_d_tbl(a3) # switch on register number
2964 /*----------------------------------------------------------------------------
2968 * t1 unbiased exponent
2969 * t2 normalized fraction
2971 *----------------------------------------------------------------------------
2973 LEAF(renorm_fs_s, 0)
2975 * Find out how many leading zero bits are in t2 and put in t9.
3003 * Now shift t2 the correct number of bits.
3006 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
3008 subu t1, t1, t9 # adjust exponent
3013 /*----------------------------------------------------------------------------
3017 * t1 unbiased exponent
3018 * t2 normalized fraction
3020 *----------------------------------------------------------------------------
3022 LEAF(renorm_fs_d, 0)
3024 * Find out how many leading zero bits are in t2 and put in t9.
3057 * Now shift t2 the correct number of bits.
3060 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
3062 subu t1, t9 # adjust exponent
3067 /*----------------------------------------------------------------------------
3071 * ta1 unbiased exponent
3072 * ta2 normalized fraction
3074 *----------------------------------------------------------------------------
3076 LEAF(renorm_ft_s, 0)
3078 * Find out how many leading zero bits are in ta2 and put in t9.
3106 * Now shift ta2 the correct number of bits.
3109 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
3111 subu ta1, t9 # adjust exponent
3116 /*----------------------------------------------------------------------------
3120 * ta1 unbiased exponent
3121 * ta2 normalized fraction
3123 *----------------------------------------------------------------------------
3125 LEAF(renorm_ft_d, 0)
3127 * Find out how many leading zero bits are in ta2 and put in t9.
3160 * Now shift ta2 the correct number of bits.
3163 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
3165 subu ta1, t9 # adjust exponent