1 /* $OpenBSD: fp.S,v 1.2 1998/03/16 09:03:31 pefo 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 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * from: @(#)fp.s 8.1 (Berkeley) 6/10/93
34 * JNPR: fp.S,v 1.1 2006/08/07 05:38:57 katta
39 * Standard header stuff.
42 #include <machine/asm.h>
43 #include <machine/regnum.h>
44 #include <machine/cpuregs.h>
49 #define DEXP_INF 0x7ff
51 #define DEXP_BIAS 1023
53 #define DEXP_MIN -1022
56 #define WEXP_MAX 30 /* maximum unbiased exponent for int */
57 #define WEXP_MIN -1 /* minimum unbiased exponent for int */
60 #define SIMPL_ONE 0x00800000
61 #define DIMPL_ONE 0x00100000
62 #define SLEAD_ZEROS 31 - 23
63 #define DLEAD_ZEROS 31 - 20
65 #define GUARDBIT 0x80000000
66 #define SSIGNAL_NAN 0x00400000
67 #define DSIGNAL_NAN 0x00080000
68 #define SQUIET_NAN 0x003fffff
69 #define DQUIET_NAN0 0x0007ffff
70 #define DQUIET_NAN1 0xffffffff
71 #define INT_MIN 0x80000000
72 #define INT_MAX 0x7fffffff
74 #define COND_UNORDERED 0x1
75 #define COND_EQUAL 0x2
77 #define COND_SIGNAL 0x8
79 /*----------------------------------------------------------------------------
83 * Emulate unimplemented floating point operations.
84 * This routine should only be called by MipsFPInterrupt().
86 * MipsEmulateFP(instr)
93 * Floating point registers are modified according to instruction.
95 *----------------------------------------------------------------------------
97 NON_LEAF(MipsEmulateFP, CALLFRAME_SIZ, ra)
98 subu sp, sp, CALLFRAME_SIZ
99 sw ra, CALLFRAME_RA(sp)
101 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
103 srl v0, a0, 21 - 2 # get FMT field
104 and v0, v0, 0xF << 2 # mask FMT field
105 and v1, a0, 0x3F # mask FUNC field
106 sll v1, v1, 5 # align for table lookup
107 bgt v0, 4 << 2, ill # illegal format
110 cfc1 a1, MIPS_FPU_CSR # get exception register
111 lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT
112 and a1, a1, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception
113 ctc1 a1, MIPS_FPU_CSR
633 * Single precision subtract.
637 xor ta0, ta0, 1 # negate FT sign bit
640 * Single precision add.
645 bne t1, SEXP_INF, 1f # is FS an infinity?
646 bne ta1, SEXP_INF, result_fs_s # if FT is not inf, result=FS
647 bne t2, zero, result_fs_s # if FS is NAN, result is FS
648 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
649 bne t0, ta0, invalid_s # both infinities same sign?
650 b result_fs_s # result is in FS
652 beq ta1, SEXP_INF, result_ft_s # if FT is inf, result=FT
653 bne t1, zero, 4f # is FS a denormalized num?
654 beq t2, zero, 3f # is FS zero?
655 bne ta1, zero, 2f # is FT a denormalized num?
656 beq ta2, zero, result_fs_s # FT is zero, result=FS
662 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
663 or ta2, ta2, SIMPL_ONE # set implied one bit
666 bne ta1, zero, result_ft_s # if FT != 0, result=FT
667 bne ta2, zero, result_ft_s
668 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
669 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
670 or t0, t0, ta0 # compute result sign
673 and t0, t0, ta0 # compute result sign
676 bne ta1, zero, 2f # is FT a denormalized num?
677 beq ta2, zero, result_fs_s # FT is zero, result=FS
678 subu t1, t1, SEXP_BIAS # unbias FS exponent
679 or t2, t2, SIMPL_ONE # set implied one bit
683 subu t1, t1, SEXP_BIAS # unbias FS exponent
684 or t2, t2, SIMPL_ONE # set implied one bit
685 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
686 or ta2, ta2, SIMPL_ONE # set implied one bit
688 * Perform the addition.
691 move t8, zero # no shifted bits (sticky reg)
692 beq t1, ta1, 4f # no shift needed
693 subu v0, t1, ta1 # v0 = difference of exponents
694 move v1, v0 # v1 = abs(difference)
698 ble v1, SFRAC_BITS+2, 2f # is difference too great?
699 li t8, STICKYBIT # set the sticky bit
700 bge v0, zero, 1f # check which exp is larger
701 move t1, ta1 # result exp is FTs
702 move t2, zero # FSs fraction shifted is zero
705 move ta2, zero # FTs fraction shifted is zero
708 li t9, 32 # compute 32 - abs(exp diff)
710 bgt v0, zero, 3f # if FS > FT, shift FTs frac
711 move t1, ta1 # FT > FS, result exp is FTs
712 sll t8, t2, t9 # save bits shifted out
713 srl t2, t2, v1 # shift FSs fraction
716 sll t8, ta2, t9 # save bits shifted out
717 srl ta2, ta2, v1 # shift FTs fraction
719 bne t0, ta0, 1f # if signs differ, subtract
720 addu t2, t2, ta2 # add fractions
723 blt t2, ta2, 3f # subtract larger from smaller
724 bne t2, ta2, 2f # if same, result=0
725 move t1, zero # result=0
727 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
728 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
729 or t0, t0, ta0 # compute result sign
732 and t0, t0, ta0 # compute result sign
735 sltu t9, zero, t8 # compute t2:zero - ta2:t8
737 subu t2, t2, ta2 # subtract fractions
738 subu t2, t2, t9 # subtract barrow
741 move t0, ta0 # sign of result = FTs
742 sltu t9, zero, t8 # compute ta2:zero - t2:t8
744 subu t2, ta2, t2 # subtract fractions
745 subu t2, t2, t9 # subtract barrow
749 * Double precision subtract.
753 xor ta0, ta0, 1 # negate sign bit
756 * Double precision add.
761 bne t1, DEXP_INF, 1f # is FS an infinity?
762 bne ta1, DEXP_INF, result_fs_d # if FT is not inf, result=FS
763 bne t2, zero, result_fs_d # if FS is NAN, result is FS
764 bne t3, zero, result_fs_d
765 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
766 bne ta3, zero, result_ft_d
767 bne t0, ta0, invalid_d # both infinities same sign?
768 b result_fs_d # result is in FS
770 beq ta1, DEXP_INF, result_ft_d # if FT is inf, result=FT
771 bne t1, zero, 4f # is FS a denormalized num?
772 bne t2, zero, 1f # is FS zero?
775 bne ta1, zero, 2f # is FT a denormalized num?
777 beq ta3, zero, result_fs_d # FT is zero, result=FS
784 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
785 or ta2, ta2, DIMPL_ONE # set implied one bit
788 bne ta1, zero, result_ft_d # if FT != 0, result=FT
789 bne ta2, zero, result_ft_d
790 bne ta3, zero, result_ft_d
791 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
792 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
793 or t0, t0, ta0 # compute result sign
796 and t0, t0, ta0 # compute result sign
799 bne ta1, zero, 2f # is FT a denormalized num?
801 beq ta3, zero, result_fs_d # FT is zero, result=FS
803 subu t1, t1, DEXP_BIAS # unbias FS exponent
804 or t2, t2, DIMPL_ONE # set implied one bit
808 subu t1, t1, DEXP_BIAS # unbias FS exponent
809 or t2, t2, DIMPL_ONE # set implied one bit
810 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
811 or ta2, ta2, DIMPL_ONE # set implied one bit
813 * Perform the addition.
816 move t8, zero # no shifted bits (sticky reg)
817 beq t1, ta1, 4f # no shift needed
818 subu v0, t1, ta1 # v0 = difference of exponents
819 move v1, v0 # v1 = abs(difference)
823 ble v1, DFRAC_BITS+2, 2f # is difference too great?
824 li t8, STICKYBIT # set the sticky bit
825 bge v0, zero, 1f # check which exp is larger
826 move t1, ta1 # result exp is FTs
827 move t2, zero # FSs fraction shifted is zero
831 move ta2, zero # FTs fraction shifted is zero
836 bge v0, zero, 3f # if FS > FT, shift FTs frac
837 move t1, ta1 # FT > FS, result exp is FTs
838 blt v1, t9, 1f # shift right by < 32?
841 sll t8, t2, t9 # save bits shifted out
842 sltu t9, zero, t3 # dont lose any one bits
843 or t8, t8, t9 # save sticky bit
844 srl t3, t2, v1 # shift FSs fraction
849 sll t8, t3, t9 # save bits shifted out
850 srl t3, t3, v1 # shift FSs fraction
851 sll t9, t2, t9 # save bits shifted out of t2
852 or t3, t3, t9 # and put into t3
856 blt v1, t9, 1f # shift right by < 32?
859 sll t8, ta2, t9 # save bits shifted out
860 srl ta3, ta2, v1 # shift FTs fraction
865 sll t8, ta3, t9 # save bits shifted out
866 srl ta3, ta3, v1 # shift FTs fraction
867 sll t9, ta2, t9 # save bits shifted out of t2
868 or ta3, ta3, t9 # and put into t3
871 bne t0, ta0, 1f # if signs differ, subtract
872 addu t3, t3, ta3 # add fractions
873 sltu t9, t3, ta3 # compute carry
874 addu t2, t2, ta2 # add fractions
875 addu t2, t2, t9 # add carry
878 blt t2, ta2, 3f # subtract larger from smaller
881 bne t3, ta3, 2f # if same, result=0
882 move t1, zero # result=0
885 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
886 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
887 or t0, t0, ta0 # compute result sign
890 and t0, t0, ta0 # compute result sign
893 beq t8, zero, 1f # compute t2:t3:zero - ta2:ta3:t8
895 sltu v0, t3, 1 # compute barrow out
896 subu t3, t3, 1 # subtract barrow
900 subu t3, t3, ta3 # subtract fractions
901 subu t2, t2, ta2 # subtract fractions
902 subu t2, t2, v0 # subtract barrow
905 move t0, ta0 # sign of result = FTs
906 beq t8, zero, 1f # compute ta2:ta3:zero - t2:t3:t8
908 sltu v0, ta3, 1 # compute barrow out
909 subu ta3, ta3, 1 # subtract barrow
913 subu t3, ta3, t3 # subtract fractions
914 subu t2, ta2, t2 # subtract fractions
915 subu t2, t2, v0 # subtract barrow
919 * Single precision multiply.
923 xor t0, t0, ta0 # compute sign of result
925 bne t1, SEXP_INF, 2f # is FS an infinity?
926 bne t2, zero, result_fs_s # if FS is a NAN, result=FS
927 bne ta1, SEXP_INF, 1f # FS is inf, is FT an infinity?
928 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
929 b result_fs_s # result is infinity
931 bne ta1, zero, result_fs_s # inf * zero? if no, result=FS
932 bne ta2, zero, result_fs_s
933 b invalid_s # infinity * zero is invalid
935 bne ta1, SEXP_INF, 1f # FS != inf, is FT an infinity?
936 bne t1, zero, result_ft_s # zero * inf? if no, result=FT
937 bne t2, zero, result_ft_s
938 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
939 b invalid_s # zero * infinity is invalid
941 bne t1, zero, 1f # is FS zero?
942 beq t2, zero, result_fs_s # result is zero
946 subu t1, t1, SEXP_BIAS # unbias FS exponent
947 or t2, t2, SIMPL_ONE # set implied one bit
949 bne ta1, zero, 1f # is FT zero?
950 beq ta2, zero, result_ft_s # result is zero
954 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
955 or ta2, ta2, SIMPL_ONE # set implied one bit
957 addu t1, t1, ta1 # compute result exponent
958 addu t1, t1, 9 # account for binary point
959 multu t2, ta2 # multiply fractions
965 * Double precision multiply.
969 xor t0, t0, ta0 # compute sign of result
971 bne t1, DEXP_INF, 2f # is FS an infinity?
972 bne t2, zero, result_fs_d # if FS is a NAN, result=FS
973 bne t3, zero, result_fs_d
974 bne ta1, DEXP_INF, 1f # FS is inf, is FT an infinity?
975 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
976 bne ta3, zero, result_ft_d
977 b result_fs_d # result is infinity
979 bne ta1, zero, result_fs_d # inf * zero? if no, result=FS
980 bne ta2, zero, result_fs_d
981 bne ta3, zero, result_fs_d
982 b invalid_d # infinity * zero is invalid
984 bne ta1, DEXP_INF, 1f # FS != inf, is FT an infinity?
985 bne t1, zero, result_ft_d # zero * inf? if no, result=FT
986 bne t2, zero, result_ft_d # if FS is a NAN, result=FS
987 bne t3, zero, result_ft_d
988 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
989 bne ta3, zero, result_ft_d
990 b invalid_d # zero * infinity is invalid
992 bne t1, zero, 2f # is FS zero?
994 beq t3, zero, result_fs_d # result is zero
999 subu t1, t1, DEXP_BIAS # unbias FS exponent
1000 or t2, t2, DIMPL_ONE # set implied one bit
1002 bne ta1, zero, 2f # is FT zero?
1004 beq ta3, zero, result_ft_d # result is zero
1009 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
1010 or ta2, ta2, DIMPL_ONE # set implied one bit
1012 addu t1, t1, ta1 # compute result exponent
1013 addu t1, t1, 12 # ???
1014 multu t3, ta3 # multiply fractions (low * low)
1015 move ta0, t2 # free up t2,t3 for result
1017 mflo a3 # save low order bits
1020 multu ta0, ta3 # multiply FS(high) * FT(low)
1022 mfhi t3 # init low result
1023 sltu v0, v0, v1 # compute carry
1025 multu ta1, ta2 # multiply FS(low) * FT(high)
1026 addu t3, t3, v0 # add carry
1032 multu ta0, ta2 # multiply FS(high) * FT(high)
1044 sltu a3, zero, a3 # reduce t8,a3 to just t8
1049 * Single precision divide.
1053 xor t0, t0, ta0 # compute sign of result
1055 bne t1, SEXP_INF, 1f # is FS an infinity?
1056 bne t2, zero, result_fs_s # if FS is NAN, result is FS
1057 bne ta1, SEXP_INF, result_fs_s # is FT an infinity?
1058 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
1059 b invalid_s # infinity/infinity is invalid
1061 bne ta1, SEXP_INF, 1f # is FT an infinity?
1062 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
1063 move t1, zero # x / infinity is zero
1067 bne t1, zero, 2f # is FS zero?
1069 bne ta1, zero, result_fs_s # FS=zero, is FT zero?
1070 beq ta2, zero, invalid_s # 0 / 0
1071 b result_fs_s # result = zero
1076 subu t1, t1, SEXP_BIAS # unbias FS exponent
1077 or t2, t2, SIMPL_ONE # set implied one bit
1079 bne ta1, zero, 2f # is FT zero?
1081 or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1082 and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled?
1083 bne v0, zero, fpe_trap
1084 ctc1 a1, MIPS_FPU_CSR # save exceptions
1085 li t1, SEXP_INF # result is infinity
1092 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
1093 or ta2, ta2, SIMPL_ONE # set implied one bit
1095 subu t1, t1, ta1 # compute exponent
1096 subu t1, t1, 3 # compensate for result position
1097 li v0, SFRAC_BITS+3 # number of bits to divide
1098 move t8, t2 # init dividend
1099 move t2, zero # init result
1101 bltu t8, ta2, 3f # is dividend >= divisor?
1103 subu t8, t8, ta2 # subtract divisor from dividend
1104 or t2, t2, 1 # remember that we did
1105 bne t8, zero, 3f # if not done, continue
1106 sll t2, t2, v0 # shift result to final position
1109 sll t8, t8, 1 # shift dividend
1110 sll t2, t2, 1 # shift result
1111 subu v0, v0, 1 # are we done?
1112 bne v0, zero, 1b # no, continue
1116 * Double precision divide.
1120 xor t0, t0, ta0 # compute sign of result
1122 bne t1, DEXP_INF, 1f # is FS an infinity?
1123 bne t2, zero, result_fs_d # if FS is NAN, result is FS
1124 bne t3, zero, result_fs_d
1125 bne ta1, DEXP_INF, result_fs_d # is FT an infinity?
1126 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
1127 bne ta3, zero, result_ft_d
1128 b invalid_d # infinity/infinity is invalid
1130 bne ta1, DEXP_INF, 1f # is FT an infinity?
1131 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
1132 bne ta3, zero, result_ft_d
1133 move t1, zero # x / infinity is zero
1138 bne t1, zero, 2f # is FS zero?
1141 bne ta1, zero, result_fs_d # FS=zero, is FT zero?
1142 bne ta2, zero, result_fs_d
1143 beq ta3, zero, invalid_d # 0 / 0
1144 b result_fs_d # result = zero
1149 subu t1, t1, DEXP_BIAS # unbias FS exponent
1150 or t2, t2, DIMPL_ONE # set implied one bit
1152 bne ta1, zero, 2f # is FT zero?
1155 or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1156 and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled?
1157 bne v0, zero, fpe_trap
1158 ctc1 a1, MIPS_FPU_CSR # Save exceptions
1159 li t1, DEXP_INF # result is infinity
1167 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
1168 or ta2, ta2, DIMPL_ONE # set implied one bit
1170 subu t1, t1, ta1 # compute exponent
1171 subu t1, t1, 3 # compensate for result position
1172 li v0, DFRAC_BITS+3 # number of bits to divide
1173 move t8, t2 # init dividend
1175 move t2, zero # init result
1178 bltu t8, ta2, 3f # is dividend >= divisor?
1182 sltu v1, t9, ta3 # subtract divisor from dividend
1186 or t3, t3, 1 # remember that we did
1187 bne t8, zero, 3f # if not done, continue
1189 li v1, 32 # shift result to final position
1190 blt v0, v1, 2f # shift < 32 bits?
1191 subu v0, v0, v1 # shift by > 32 bits
1192 sll t2, t3, v0 # shift upper part
1196 subu v1, v1, v0 # shift by < 32 bits
1197 sll t2, t2, v0 # shift upper part
1198 srl t9, t3, v1 # save bits shifted out
1199 or t2, t2, t9 # and put into upper part
1203 sll t8, t8, 1 # shift dividend
1204 srl v1, t9, 31 # save bit shifted out
1205 or t8, t8, v1 # and put into upper part
1207 sll t2, t2, 1 # shift result
1208 srl v1, t3, 31 # save bit shifted out
1209 or t2, t2, v1 # and put into upper part
1211 subu v0, v0, 1 # are we done?
1212 bne v0, zero, 1b # no, continue
1213 sltu v0, zero, t9 # be sure to save any one bits
1214 or t8, t8, v0 # from the lower remainder
1218 * Single precision absolute value.
1222 move t0, zero # set sign positive
1226 * Double precision absolute value.
1230 move t0, zero # set sign positive
1234 * Single precision move.
1241 * Double precision move.
1248 * Single precision negate.
1252 xor t0, t0, 1 # reverse sign
1256 * Double precision negate.
1260 xor t0, t0, 1 # reverse sign
1264 * Convert double to single.
1268 bne t1, DEXP_INF, 1f # is FS an infinity?
1269 li t1, SEXP_INF # convert to single
1270 sll t2, t2, 3 # convert D fraction to S
1275 bne t1, zero, 2f # is FS zero?
1277 beq t3, zero, result_fs_s # result=0
1280 subu t1, t1, 3 # correct exp for shift below
1283 subu t1, t1, DEXP_BIAS # unbias exponent
1284 or t2, t2, DIMPL_ONE # add implied one bit
1286 sll t2, t2, 3 # convert D fraction to S
1293 * Convert integer to single.
1297 bne t2, zero, 1f # check for zero
1301 * Find out how many leading zero bits are in t2 and put in t9.
1330 * Now shift t2 the correct number of bits.
1333 subu t9, t9, SLEAD_ZEROS # dont count leading zeros
1334 li t1, 23 # init exponent
1335 subu t1, t1, t9 # compute exponent
1338 blt t9, zero, 2f # if shift < 0, shift right
1340 sll t2, t2, t9 # shift left
1342 add t1, t1, SEXP_BIAS # bias exponent
1343 and t2, t2, ~SIMPL_ONE # clear implied one bit
1346 negu t9 # shift right by t9
1348 sll t8, t2, v0 # save bits shifted out
1353 * Convert single to double.
1358 bne t1, SEXP_INF, 1f # is FS an infinity?
1359 li t1, DEXP_INF # convert to double
1362 bne t1, zero, 2f # is FS denormalized or zero?
1363 beq t2, zero, result_fs_d # is FS zero?
1368 addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly
1369 sll t3, t2, 32 - 3 # convert S fraction to D
1374 * Convert integer to double.
1378 bne t2, zero, 1f # check for zero
1379 move t1, zero # result=0
1383 * Find out how many leading zero bits are in t2 and put in t9.
1412 * Now shift t2 the correct number of bits.
1415 subu t9, t9, DLEAD_ZEROS # dont count leading zeros
1416 li t1, DEXP_BIAS + 20 # init exponent
1417 subu t1, t1, t9 # compute exponent
1420 blt t9, zero, 2f # if shift < 0, shift right
1422 sll t2, t2, t9 # shift left
1424 and t2, t2, ~DIMPL_ONE # clear implied one bit
1428 negu t9 # shift right by t9
1432 and t2, t2, ~DIMPL_ONE # clear implied one bit
1436 * Convert single to integer.
1440 bne t1, SEXP_INF, 1f # is FS an infinity?
1441 bne t2, zero, invalid_w # invalid conversion
1443 bne t1, zero, 1f # is FS zero?
1444 beq t2, zero, result_fs_w # result is zero
1445 move t2, zero # result is an inexact zero
1448 subu t1, t1, SEXP_BIAS # unbias exponent
1449 or t2, t2, SIMPL_ONE # add implied one bit
1450 sll t3, t2, 32 - 3 # convert S fraction to D
1455 * Convert double to integer.
1459 bne t1, DEXP_INF, 1f # is FS an infinity?
1460 bne t2, zero, invalid_w # invalid conversion
1461 bne t3, zero, invalid_w # invalid conversion
1463 bne t1, zero, 2f # is FS zero?
1465 beq t3, zero, result_fs_w # result is zero
1467 move t2, zero # result is an inexact zero
1470 subu t1, t1, DEXP_BIAS # unbias exponent
1471 or t2, t2, DIMPL_ONE # add implied one bit
1473 blt t1, WEXP_MIN, underflow_w # is exponent too small?
1475 bgt t1, v0, overflow_w # is exponent too large?
1476 bne t1, v0, 1f # special check for INT_MIN
1477 beq t0, zero, overflow_w # if positive, overflow
1478 bne t2, DIMPL_ONE, overflow_w
1479 bne t3, zero, overflow_w
1480 li t2, INT_MIN # result is INT_MIN
1483 subu v0, t1, 20 # compute amount to shift
1484 beq v0, zero, 2f # is shift needed?
1486 blt v0, zero, 1f # if shift < 0, shift right
1487 subu v1, v1, v0 # shift left
1489 srl t9, t3, v1 # save bits shifted out of t3
1490 or t2, t2, t9 # and put into t2
1491 sll t3, t3, v0 # shift FSs fraction
1494 negu v0 # shift right by v0
1496 sll t8, t3, v1 # save bits shifted out
1497 sltu t8, zero, t8 # dont lose any ones
1498 srl t3, t3, v0 # shift FSs fraction
1500 sll t9, t2, v1 # save bits shifted out of t2
1501 or t3, t3, t9 # and put into t3
1504 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1507 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1508 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1509 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1510 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1511 beq t0, zero, 5f # if sign is positive, truncate
1514 bne t0, zero, 5f # if sign is negative, truncate
1516 beq t3, zero, 5f # if no fraction bits, continue
1517 addu t2, t2, 1 # add rounding bit
1518 blt t2, zero, overflow_w # overflow?
1521 li v0, GUARDBIT # load guard bit for rounding
1522 addu v0, v0, t3 # add remainder
1523 sltu v1, v0, t3 # compute carry out
1524 beq v1, zero, 4f # if no carry, continue
1525 addu t2, t2, 1 # add carry to result
1526 blt t2, zero, overflow_w # overflow?
1528 bne v0, zero, 5f # if rounded remainder is zero
1529 and t2, t2, ~1 # clear LSB (round to nearest)
1531 beq t0, zero, 1f # result positive?
1532 negu t2 # convert to negative integer
1534 beq t3, zero, result_fs_w # is result exact?
1536 * Handle inexact exception.
1539 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1540 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1541 bne v0, zero, fpe_trap
1542 ctc1 a1, MIPS_FPU_CSR # save exceptions
1546 * Conversions to integer which overflow will trap (if enabled),
1547 * or generate an inexact trap (if enabled),
1548 * or generate an invalid exception.
1551 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1552 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1553 bne v0, zero, fpe_trap
1554 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1555 bne v0, zero, inexact_w # inexact traps enabled?
1559 * Conversions to integer which underflow will trap (if enabled),
1560 * or generate an inexact trap (if enabled),
1561 * or generate an invalid exception.
1564 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1565 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1566 bne v0, zero, fpe_trap
1567 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1568 bne v0, zero, inexact_w # inexact traps enabled?
1576 bne t1, SEXP_INF, 1f # is FS an infinity?
1577 bne t2, zero, unordered # FS is a NAN
1579 bne ta1, SEXP_INF, 2f # is FT an infinity?
1580 bne ta2, zero, unordered # FT is a NAN
1582 sll t1, t1, 23 # reassemble exp & frac
1584 sll ta1, ta1, 23 # reassemble exp & frac
1586 beq t0, zero, 1f # is FS positive?
1589 beq ta0, zero, 1f # is FT positive?
1593 blt t1, ta1, test_cond # is FS < FT?
1595 beq t1, ta1, test_cond # is FS == FT?
1596 move v0, zero # FS > FT
1604 bne t1, DEXP_INF, 1f # is FS an infinity?
1605 bne t2, zero, unordered
1606 bne t3, zero, unordered # FS is a NAN
1608 bne ta1, DEXP_INF, 2f # is FT an infinity?
1609 bne ta2, zero, unordered
1610 bne ta3, zero, unordered # FT is a NAN
1612 sll t1, t1, 20 # reassemble exp & frac
1614 sll ta1, ta1, 20 # reassemble exp & frac
1616 beq t0, zero, 1f # is FS positive?
1617 not t3 # negate t1,t3
1620 seq v0, t3, zero # compute carry
1623 beq ta0, zero, 1f # is FT positive?
1624 not ta3 # negate ta1,ta3
1627 seq v0, ta3, zero # compute carry
1631 blt t1, ta1, test_cond # is FS(MSW) < FT(MSW)?
1633 bne t1, ta1, test_cond # is FS(MSW) > FT(MSW)?
1635 bltu t3, ta3, test_cond # is FS(LSW) < FT(LSW)?
1637 beq t3, ta3, test_cond # is FS(LSW) == FT(LSW)?
1638 move v0, zero # FS > FT
1640 and v0, v0, a0 # condition match instruction?
1643 and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit
1646 or a1, a1, MIPS_FPU_COND_BIT # set condition bit
1648 ctc1 a1, MIPS_FPU_CSR # save condition bit
1652 and v0, a0, COND_UNORDERED # this cmp match unordered?
1654 and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit
1657 or a1, a1, MIPS_FPU_COND_BIT # set condition bit
1659 and v0, a0, COND_SIGNAL
1660 beq v0, zero, 1f # is this a signaling cmp?
1661 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
1662 and v0, a1, MIPS_FPU_ENABLE_INVALID
1663 bne v0, zero, fpe_trap
1665 ctc1 a1, MIPS_FPU_CSR # save condition bit
1669 * Determine the amount to shift the fraction in order to restore the
1670 * normalized position. After that, round and handle exceptions.
1674 move t9, zero # t9 = num of leading zeros
1703 * Now shift t2,t8 the correct number of bits.
1706 subu t9, t9, SLEAD_ZEROS # dont count leading zeros
1707 subu t1, t1, t9 # adjust the exponent
1708 beq t9, zero, norm_noshift_s
1710 blt t9, zero, 1f # if shift < 0, shift right
1712 sll t2, t2, t9 # shift t2,t8 left
1713 srl v0, t8, v1 # save bits shifted out
1718 negu t9 # shift t2,t8 right by t9
1720 sll v0, t8, v1 # save bits shifted out
1721 sltu v0, zero, v0 # be sure to save any one bits
1724 sll v0, t2, v1 # save bits shifted out
1728 move ta1, t1 # save unrounded exponent
1729 move ta2, t2 # save unrounded fraction
1730 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1731 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1732 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1733 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1734 beq t0, zero, 5f # if sign is positive, truncate
1737 bne t0, zero, 5f # if sign is negative, truncate
1739 beq t8, zero, 5f # if exact, continue
1740 addu t2, t2, 1 # add rounding bit
1741 bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent?
1742 addu t1, t1, 1 # adjust exponent
1743 srl t2, t2, 1 # renormalize fraction
1746 li v0, GUARDBIT # load guard bit for rounding
1747 addu v0, v0, t8 # add remainder
1748 sltu v1, v0, t8 # compute carry out
1749 beq v1, zero, 4f # if no carry, continue
1750 addu t2, t2, 1 # add carry to result
1751 bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent?
1752 addu t1, t1, 1 # adjust exponent
1753 srl t2, t2, 1 # renormalize fraction
1755 bne v0, zero, 5f # if rounded remainder is zero
1756 and t2, t2, ~1 # clear LSB (round to nearest)
1758 bgt t1, SEXP_MAX, overflow_s # overflow?
1759 blt t1, SEXP_MIN, underflow_s # underflow?
1760 bne t8, zero, inexact_s # is result inexact?
1761 addu t1, t1, SEXP_BIAS # bias exponent
1762 and t2, t2, ~SIMPL_ONE # clear implied one bit
1766 * Handle inexact exception.
1769 addu t1, t1, SEXP_BIAS # bias exponent
1770 and t2, t2, ~SIMPL_ONE # clear implied one bit
1772 jal set_fd_s # save result
1773 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1774 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1775 bne v0, zero, fpe_trap
1776 ctc1 a1, MIPS_FPU_CSR # save exceptions
1780 * Overflow will trap (if enabled),
1781 * or generate an inexact trap (if enabled),
1782 * or generate an infinity.
1785 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1786 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1788 subu t1, t1, 192 # bias exponent
1789 and t2, t2, ~SIMPL_ONE # clear implied one bit
1790 jal set_fd_s # save result
1793 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1794 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1795 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate)
1796 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity
1799 li t1, SEXP_MAX # result is max finite
1805 li t1, SEXP_MAX + 1 # result is infinity
1810 * In this implementation, "tininess" is detected "after rounding" and
1811 * "loss of accuracy" is detected as "an inexact result".
1814 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1817 * Underflow is enabled so compute the result and trap.
1819 addu t1, t1, 192 # bias exponent
1820 and t2, t2, ~SIMPL_ONE # clear implied one bit
1821 jal set_fd_s # save result
1822 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1825 * Underflow is not enabled so compute the result,
1826 * signal inexact result (if it is) and trap (if enabled).
1829 move t1, ta1 # get unrounded exponent
1830 move t2, ta2 # get unrounded fraction
1831 li t9, SEXP_MIN # compute shift amount
1832 subu t9, t9, t1 # shift t2,t8 right by t9
1833 blt t9, SFRAC_BITS+2, 3f # shift all the bits out?
1834 move t1, zero # result is inexact zero
1836 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1838 * Now round the zero result.
1839 * Only need to worry about rounding to +- infinity when the sign matches.
1841 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1842 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest
1843 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero
1844 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1845 beq t0, zero, inexact_nobias_s # if sign is positive, truncate
1848 bne t0, zero, inexact_nobias_s # if sign is negative, truncate
1850 addu t2, t2, 1 # add rounding bit
1855 sltu v0, zero, t8 # be sure to save any one bits
1856 sll t8, t2, v1 # save bits shifted out
1857 or t8, t8, v0 # include sticky bits
1860 * Now round the denormalized result.
1862 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1863 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1864 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1865 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1866 beq t0, zero, 5f # if sign is positive, truncate
1869 bne t0, zero, 5f # if sign is negative, truncate
1871 beq t8, zero, 5f # if exact, continue
1872 addu t2, t2, 1 # add rounding bit
1875 li v0, GUARDBIT # load guard bit for rounding
1876 addu v0, v0, t8 # add remainder
1877 sltu v1, v0, t8 # compute carry out
1878 beq v1, zero, 4f # if no carry, continue
1879 addu t2, t2, 1 # add carry to result
1881 bne v0, zero, 5f # if rounded remainder is zero
1882 and t2, t2, ~1 # clear LSB (round to nearest)
1884 move t1, zero # denorm or zero exponent
1885 jal set_fd_s # save result
1886 beq t8, zero, done # check for exact result
1887 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1888 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1889 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1890 bne v0, zero, fpe_trap
1891 ctc1 a1, MIPS_FPU_CSR # save exceptions
1895 * Determine the amount to shift the fraction in order to restore the
1896 * normalized position. After that, round and handle exceptions.
1900 move t9, zero # t9 = num of leading zeros
1932 * Now shift t2,t3,t8 the correct number of bits.
1935 subu t9, t9, DLEAD_ZEROS # dont count leading zeros
1936 subu t1, t1, t9 # adjust the exponent
1937 beq t9, zero, norm_noshift_d
1939 blt t9, zero, 2f # if shift < 0, shift right
1940 blt t9, v1, 1f # shift by < 32?
1941 subu t9, t9, v1 # shift by >= 32
1943 sll t2, t3, t9 # shift left by t9
1944 srl v0, t8, v1 # save bits shifted out
1951 sll t2, t2, t9 # shift left by t9
1952 srl v0, t3, v1 # save bits shifted out
1955 srl v0, t8, v1 # save bits shifted out
1960 negu t9 # shift right by t9
1961 subu v1, v1, t9 # (known to be < 32 bits)
1962 sll v0, t8, v1 # save bits shifted out
1963 sltu v0, zero, v0 # be sure to save any one bits
1966 sll v0, t3, v1 # save bits shifted out
1969 sll v0, t2, v1 # save bits shifted out
1973 move ta1, t1 # save unrounded exponent
1974 move ta2, t2 # save unrounded fraction (MS)
1975 move ta3, t3 # save unrounded fraction (LS)
1976 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1977 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1978 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1979 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1980 beq t0, zero, 5f # if sign is positive, truncate
1983 bne t0, zero, 5f # if sign is negative, truncate
1985 beq t8, zero, 5f # if exact, continue
1986 addu t3, t3, 1 # add rounding bit
1987 bne t3, zero, 5f # branch if no carry
1988 addu t2, t2, 1 # add carry
1989 bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent?
1990 addu t1, t1, 1 # adjust exponent
1991 srl t2, t2, 1 # renormalize fraction
1994 li v0, GUARDBIT # load guard bit for rounding
1995 addu v0, v0, t8 # add remainder
1996 sltu v1, v0, t8 # compute carry out
1997 beq v1, zero, 4f # branch if no carry
1998 addu t3, t3, 1 # add carry
1999 bne t3, zero, 4f # branch if no carry
2000 addu t2, t2, 1 # add carry to result
2001 bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent?
2002 addu t1, t1, 1 # adjust exponent
2003 srl t2, t2, 1 # renormalize fraction
2005 bne v0, zero, 5f # if rounded remainder is zero
2006 and t3, t3, ~1 # clear LSB (round to nearest)
2008 bgt t1, DEXP_MAX, overflow_d # overflow?
2009 blt t1, DEXP_MIN, underflow_d # underflow?
2010 bne t8, zero, inexact_d # is result inexact?
2011 addu t1, t1, DEXP_BIAS # bias exponent
2012 and t2, t2, ~DIMPL_ONE # clear implied one bit
2016 * Handle inexact exception.
2019 addu t1, t1, DEXP_BIAS # bias exponent
2020 and t2, t2, ~DIMPL_ONE # clear implied one bit
2022 jal set_fd_d # save result
2023 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2024 and v0, a1, MIPS_FPU_ENABLE_INEXACT
2025 bne v0, zero, fpe_trap
2026 ctc1 a1, MIPS_FPU_CSR # save exceptions
2030 * Overflow will trap (if enabled),
2031 * or generate an inexact trap (if enabled),
2032 * or generate an infinity.
2035 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
2036 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
2038 subu t1, t1, 1536 # bias exponent
2039 and t2, t2, ~DIMPL_ONE # clear implied one bit
2040 jal set_fd_d # save result
2043 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
2044 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
2045 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate)
2046 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity
2049 li t1, DEXP_MAX # result is max finite
2056 li t1, DEXP_MAX + 1 # result is infinity
2062 * In this implementation, "tininess" is detected "after rounding" and
2063 * "loss of accuracy" is detected as "an inexact result".
2066 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
2069 * Underflow is enabled so compute the result and trap.
2071 addu t1, t1, 1536 # bias exponent
2072 and t2, t2, ~DIMPL_ONE # clear implied one bit
2073 jal set_fd_d # save result
2074 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2077 * Underflow is not enabled so compute the result,
2078 * signal inexact result (if it is) and trap (if enabled).
2081 move t1, ta1 # get unrounded exponent
2082 move t2, ta2 # get unrounded fraction (MS)
2083 move t3, ta3 # get unrounded fraction (LS)
2084 li t9, DEXP_MIN # compute shift amount
2085 subu t9, t9, t1 # shift t2,t8 right by t9
2086 blt t9, DFRAC_BITS+2, 3f # shift all the bits out?
2087 move t1, zero # result is inexact zero
2090 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2092 * Now round the zero result.
2093 * Only need to worry about rounding to +- infinity when the sign matches.
2095 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
2096 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_d # round to nearest
2097 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d # round to zero
2098 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
2099 beq t0, zero, inexact_nobias_d # if sign is positive, truncate
2102 bne t0, zero, inexact_nobias_d # if sign is negative, truncate
2104 addu t3, t3, 1 # add rounding bit
2108 blt t9, v1, 1f # shift by < 32?
2109 subu t9, t9, v1 # shift right by >= 32
2111 sltu v0, zero, t8 # be sure to save any one bits
2112 sll t8, t2, v1 # save bits shifted out
2113 or t8, t8, v0 # include sticky bits
2118 subu v1, v1, t9 # shift right by t9
2119 sltu v0, zero, t8 # be sure to save any one bits
2120 sll t8, t3, v1 # save bits shifted out
2121 or t8, t8, v0 # include sticky bits
2123 sll v0, t2, v1 # save bits shifted out
2127 * Now round the denormalized result.
2130 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
2131 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
2132 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
2133 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
2134 beq t0, zero, 5f # if sign is positive, truncate
2137 bne t0, zero, 5f # if sign is negative, truncate
2139 beq t8, zero, 5f # if exact, continue
2140 addu t3, t3, 1 # add rounding bit
2141 bne t3, zero, 5f # if no carry, continue
2142 addu t2, t2, 1 # add carry
2145 li v0, GUARDBIT # load guard bit for rounding
2146 addu v0, v0, t8 # add remainder
2147 sltu v1, v0, t8 # compute carry out
2148 beq v1, zero, 4f # if no carry, continue
2149 addu t3, t3, 1 # add rounding bit
2150 bne t3, zero, 4f # if no carry, continue
2151 addu t2, t2, 1 # add carry
2153 bne v0, zero, 5f # if rounded remainder is zero
2154 and t3, t3, ~1 # clear LSB (round to nearest)
2156 move t1, zero # denorm or zero exponent
2157 jal set_fd_d # save result
2158 beq t8, zero, done # check for exact result
2159 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2160 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2161 and v0, a1, MIPS_FPU_ENABLE_INEXACT
2162 bne v0, zero, fpe_trap
2163 ctc1 a1, MIPS_FPU_CSR # save exceptions
2167 * Signal an invalid operation if the trap is enabled; otherwise,
2168 * the result is a quiet NAN.
2170 invalid_s: # trap invalid operation
2171 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2172 and v0, a1, MIPS_FPU_ENABLE_INVALID
2173 bne v0, zero, fpe_trap
2174 ctc1 a1, MIPS_FPU_CSR # save exceptions
2175 move t0, zero # result is a quiet NAN
2178 jal set_fd_s # save result (in t0,t1,t2)
2182 * Signal an invalid operation if the trap is enabled; otherwise,
2183 * the result is a quiet NAN.
2185 invalid_d: # trap invalid operation
2186 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2187 and v0, a1, MIPS_FPU_ENABLE_INVALID
2188 bne v0, zero, fpe_trap
2189 ctc1 a1, MIPS_FPU_CSR # save exceptions
2190 move t0, zero # result is a quiet NAN
2194 jal set_fd_d # save result (in t0,t1,t2,t3)
2198 * Signal an invalid operation if the trap is enabled; otherwise,
2199 * the result is INT_MAX or INT_MIN.
2201 invalid_w: # trap invalid operation
2202 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2203 and v0, a1, MIPS_FPU_ENABLE_INVALID
2204 bne v0, zero, fpe_trap
2205 ctc1 a1, MIPS_FPU_CSR # save exceptions
2207 li t2, INT_MAX # result is INT_MAX
2210 li t2, INT_MIN # result is INT_MIN
2214 * Trap if the hardware should have handled this case.
2217 move a2, a1 # code = FP CSR
2218 ctc1 a1, MIPS_FPU_CSR # save exceptions
2222 * Send an illegal instruction signal to the current process.
2225 ctc1 a1, MIPS_FPU_CSR # save exceptions
2226 move a2, a0 # code = FP instruction
2230 move t0, ta0 # result is FT
2233 result_fs_s: # result is FS
2234 jal set_fd_s # save result (in t0,t1,t2)
2238 jal set_fd_word # save result (in t2)
2242 move t0, ta0 # result is FT
2246 result_fs_d: # result is FS
2247 jal set_fd_d # save result (in t0,t1,t2,t3)
2250 lw ra, CALLFRAME_RA(sp)
2251 addu sp, sp, CALLFRAME_SIZ
2255 /*----------------------------------------------------------------------------
2258 * Read (integer) the FS register (bits 15-11).
2259 * This is an internal routine used by MipsEmulateFP only.
2262 * t0 contains the sign
2263 * t2 contains the fraction
2265 *----------------------------------------------------------------------------
2268 srl a3, a0, 12 - 2 # get FS field (even regs only)
2269 and a3, a3, 0xF << 2 # mask FS field
2270 lw a3, get_fs_int_tbl(a3) # switch on register number
2280 .word get_fs_int_f10
2281 .word get_fs_int_f12
2282 .word get_fs_int_f14
2283 .word get_fs_int_f16
2284 .word get_fs_int_f18
2285 .word get_fs_int_f20
2286 .word get_fs_int_f22
2287 .word get_fs_int_f24
2288 .word get_fs_int_f26
2289 .word get_fs_int_f28
2290 .word get_fs_int_f30
2341 srl t0, t2, 31 # init the sign bit
2348 /*----------------------------------------------------------------------------
2351 * Read (single precision) the FT register (bits 20-16) and
2352 * the FS register (bits 15-11) and break up into fields.
2353 * This is an internal routine used by MipsEmulateFP only.
2356 * t0 contains the FS sign
2357 * t1 contains the FS (biased) exponent
2358 * t2 contains the FS fraction
2359 * ta0 contains the FT sign
2360 * ta1 contains the FT (biased) exponent
2361 * ta2 contains the FT fraction
2363 *----------------------------------------------------------------------------
2366 srl a3, a0, 17 - 2 # get FT field (even regs only)
2367 and a3, a3, 0xF << 2 # mask FT field
2368 lw a3, get_ft_s_tbl(a3) # switch on register number
2439 srl ta1, ta0, 23 # get exponent
2441 and ta2, ta0, 0x7FFFFF # get fraction
2442 srl ta0, ta0, 31 # get sign
2443 bne ta1, SEXP_INF, 1f # is it a signaling NAN?
2444 and v0, ta2, SSIGNAL_NAN
2445 bne v0, zero, invalid_s
2447 /* fall through to get FS */
2449 /*----------------------------------------------------------------------------
2452 * Read (single precision) the FS register (bits 15-11) and
2453 * break up into fields.
2454 * This is an internal routine used by MipsEmulateFP only.
2457 * t0 contains the sign
2458 * t1 contains the (biased) exponent
2459 * t2 contains the fraction
2461 *----------------------------------------------------------------------------
2464 srl a3, a0, 12 - 2 # get FS field (even regs only)
2465 and a3, a3, 0xF << 2 # mask FS field
2466 lw a3, get_fs_s_tbl(a3) # switch on register number
2537 srl t1, t0, 23 # get exponent
2539 and t2, t0, 0x7FFFFF # get fraction
2540 srl t0, t0, 31 # get sign
2541 bne t1, SEXP_INF, 1f # is it a signaling NAN?
2542 and v0, t2, SSIGNAL_NAN
2543 bne v0, zero, invalid_s
2548 /*----------------------------------------------------------------------------
2551 * Read (double precision) the FT register (bits 20-16) and
2552 * the FS register (bits 15-11) and break up into fields.
2553 * This is an internal routine used by MipsEmulateFP only.
2556 * t0 contains the FS sign
2557 * t1 contains the FS (biased) exponent
2558 * t2 contains the FS fraction
2559 * t3 contains the FS remaining fraction
2560 * ta0 contains the FT sign
2561 * ta1 contains the FT (biased) exponent
2562 * ta2 contains the FT fraction
2563 * ta3 contains the FT remaining fraction
2565 *----------------------------------------------------------------------------
2568 srl a3, a0, 17 - 2 # get FT field (even regs only)
2569 and a3, a3, 0xF << 2 # mask FT field
2570 lw a3, get_ft_d_tbl(a3) # switch on register number
2657 srl ta1, ta0, 20 # get exponent
2659 and ta2, ta0, 0xFFFFF # get fraction
2660 srl ta0, ta0, 31 # get sign
2661 bne ta1, DEXP_INF, 1f # is it a signaling NAN?
2662 and v0, ta2, DSIGNAL_NAN
2663 bne v0, zero, invalid_d
2665 /* fall through to get FS */
2667 /*----------------------------------------------------------------------------
2670 * Read (double precision) the FS register (bits 15-11) and
2671 * break up into fields.
2672 * This is an internal routine used by MipsEmulateFP only.
2675 * t0 contains the sign
2676 * t1 contains the (biased) exponent
2677 * t2 contains the fraction
2678 * t3 contains the remaining fraction
2680 *----------------------------------------------------------------------------
2683 srl a3, a0, 12 - 2 # get FS field (even regs only)
2684 and a3, a3, 0xF << 2 # mask FS field
2685 lw a3, get_fs_d_tbl(a3) # switch on register number
2772 srl t1, t0, 20 # get exponent
2774 and t2, t0, 0xFFFFF # get fraction
2775 srl t0, t0, 31 # get sign
2776 bne t1, DEXP_INF, 1f # is it a signaling NAN?
2777 and v0, t2, DSIGNAL_NAN
2778 bne v0, zero, invalid_d
2783 /*----------------------------------------------------------------------------
2786 * Read (single precision) the FS register (bits 15-11) and
2787 * the FT register (bits 20-16) and break up into fields.
2788 * This is an internal routine used by MipsEmulateFP only.
2791 * t0 contains the sign
2792 * t1 contains the (biased) exponent
2793 * t2 contains the fraction
2794 * ta0 contains the sign
2795 * ta1 contains the (biased) exponent
2796 * ta2 contains the fraction
2798 *----------------------------------------------------------------------------
2801 srl a3, a0, 12 - 2 # get FS field (even regs only)
2802 and a3, a3, 0xF << 2 # mask FS field
2803 lw a3, cmp_fs_s_tbl(a3) # switch on register number
2874 srl t1, t0, 23 # get exponent
2876 and t2, t0, 0x7FFFFF # get fraction
2877 srl t0, t0, 31 # get sign
2879 srl a3, a0, 17 - 2 # get FT field (even regs only)
2880 and a3, a3, 0xF << 2 # mask FT field
2881 lw a3, cmp_ft_s_tbl(a3) # switch on register number
2952 srl ta1, ta0, 23 # get exponent
2954 and ta2, ta0, 0x7FFFFF # get fraction
2955 srl ta0, ta0, 31 # get sign
2959 /*----------------------------------------------------------------------------
2962 * Read (double precision) the FS register (bits 15-11) and
2963 * the FT register (bits 20-16) and break up into fields.
2964 * This is an internal routine used by MipsEmulateFP only.
2967 * t0 contains the sign
2968 * t1 contains the (biased) exponent
2969 * t2 contains the fraction
2970 * t3 contains the remaining fraction
2971 * ta0 contains the sign
2972 * ta1 contains the (biased) exponent
2973 * ta2 contains the fraction
2974 * ta3 contains the remaining fraction
2976 *----------------------------------------------------------------------------
2979 srl a3, a0, 12 - 2 # get FS field (even regs only)
2980 and a3, a3, 0xF << 2 # mask FS field
2981 lw a3, cmp_fs_d_tbl(a3) # switch on register number
3068 srl t1, t0, 20 # get exponent
3070 and t2, t0, 0xFFFFF # get fraction
3071 srl t0, t0, 31 # get sign
3073 srl a3, a0, 17 - 2 # get FT field (even regs only)
3074 and a3, a3, 0xF << 2 # mask FT field
3075 lw a3, cmp_ft_d_tbl(a3) # switch on register number
3162 srl ta1, ta0, 20 # get exponent
3164 and ta2, ta0, 0xFFFFF # get fraction
3165 srl ta0, ta0, 31 # get sign
3169 /*----------------------------------------------------------------------------
3172 * Write (single precision) the FD register (bits 10-6).
3173 * This is an internal routine used by MipsEmulateFP only.
3176 * a0 contains the FP instruction
3177 * t0 contains the sign
3178 * t1 contains the (biased) exponent
3179 * t2 contains the fraction
3183 * Write (integer) the FD register (bits 10-6).
3184 * This is an internal routine used by MipsEmulateFP only.
3187 * a0 contains the FP instruction
3188 * t2 contains the integer
3190 *----------------------------------------------------------------------------
3193 sll t0, t0, 31 # position sign
3194 sll t1, t1, 23 # position exponent
3198 srl a3, a0, 7 - 2 # get FD field (even regs only)
3199 and a3, a3, 0xF << 2 # mask FT field
3200 lw a3, set_fd_s_tbl(a3) # switch on register number
3273 /*----------------------------------------------------------------------------
3276 * Write (double precision) the FT register (bits 10-6).
3277 * This is an internal routine used by MipsEmulateFP only.
3280 * a0 contains the FP instruction
3281 * t0 contains the sign
3282 * t1 contains the (biased) exponent
3283 * t2 contains the fraction
3284 * t3 contains the remaining fraction
3286 *----------------------------------------------------------------------------
3289 sll t0, t0, 31 # set sign
3290 sll t1, t1, 20 # set exponent
3292 or t0, t0, t2 # set fraction
3293 srl a3, a0, 7 - 2 # get FD field (even regs only)
3294 and a3, a3, 0xF << 2 # mask FD field
3295 lw a3, set_fd_d_tbl(a3) # switch on register number
3384 /*----------------------------------------------------------------------------
3388 * t1 unbiased exponent
3389 * t2 normalized fraction
3391 *----------------------------------------------------------------------------
3395 * Find out how many leading zero bits are in t2 and put in t9.
3423 * Now shift t2 the correct number of bits.
3426 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
3428 subu t1, t1, t9 # adjust exponent
3433 /*----------------------------------------------------------------------------
3437 * t1 unbiased exponent
3438 * t2,t3 normalized fraction
3440 *----------------------------------------------------------------------------
3444 * Find out how many leading zero bits are in t2,t3 and put in t9.
3476 * Now shift t2,t3 the correct number of bits.
3479 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
3481 subu t1, t1, t9 # adjust exponent
3484 subu t9, t9, v0 # shift fraction left >= 32 bits
3489 subu v0, v0, t9 # shift fraction left < 32 bits
3497 /*----------------------------------------------------------------------------
3501 * ta1 unbiased exponent
3502 * ta2 normalized fraction
3504 *----------------------------------------------------------------------------
3508 * Find out how many leading zero bits are in ta2 and put in t9.
3536 * Now shift ta2 the correct number of bits.
3539 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
3541 subu ta1, ta1, t9 # adjust exponent
3546 /*----------------------------------------------------------------------------
3550 * ta1 unbiased exponent
3551 * ta2,ta3 normalized fraction
3553 *----------------------------------------------------------------------------
3557 * Find out how many leading zero bits are in ta2,ta3 and put in t9.
3589 * Now shift ta2,ta3 the correct number of bits.
3592 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
3594 subu ta1, ta1, t9 # adjust exponent
3597 subu t9, t9, v0 # shift fraction left >= 32 bits
3602 subu v0, v0, t9 # shift fraction left < 32 bits