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
81 /*----------------------------------------------------------------------------
85 * Emulate unimplemented floating point operations.
86 * This routine should only be called by MipsFPInterrupt().
88 * MipsEmulateFP(instr)
95 * Floating point registers are modified according to instruction.
97 *----------------------------------------------------------------------------
99 NESTED(MipsEmulateFP, CALLFRAME_SIZ, ra)
100 subu sp, sp, CALLFRAME_SIZ
101 sw ra, CALLFRAME_RA(sp)
103 * Decode the FMT field (bits 24-21) and FUNCTION field (bits 5-0).
105 srl v0, a0, 21 - 2 # get FMT field
106 and v0, v0, 0xF << 2 # mask FMT field
107 and v1, a0, 0x3F # mask FUNC field
108 sll v1, v1, 5 # align for table lookup
109 bgt v0, 4 << 2, ill # illegal format
112 cfc1 a1, MIPS_FPU_CSR # get exception register
113 lw a3, func_fmt_tbl(v1) # switch on FUNC & FMT
114 and a1, a1, ~MIPS_FPU_EXCEPTION_UNIMPL # clear exception
115 ctc1 a1, MIPS_FPU_CSR
635 * Single precision subtract.
639 xor ta0, ta0, 1 # negate FT sign bit
642 * Single precision add.
647 bne t1, SEXP_INF, 1f # is FS an infinity?
648 bne ta1, SEXP_INF, result_fs_s # if FT is not inf, result=FS
649 bne t2, zero, result_fs_s # if FS is NAN, result is FS
650 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
651 bne t0, ta0, invalid_s # both infinities same sign?
652 b result_fs_s # result is in FS
654 beq ta1, SEXP_INF, result_ft_s # if FT is inf, result=FT
655 bne t1, zero, 4f # is FS a denormalized num?
656 beq t2, zero, 3f # is FS zero?
657 bne ta1, zero, 2f # is FT a denormalized num?
658 beq ta2, zero, result_fs_s # FT is zero, result=FS
664 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
665 or ta2, ta2, SIMPL_ONE # set implied one bit
668 bne ta1, zero, result_ft_s # if FT != 0, result=FT
669 bne ta2, zero, result_ft_s
670 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
671 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
672 or t0, t0, ta0 # compute result sign
675 and t0, t0, ta0 # compute result sign
678 bne ta1, zero, 2f # is FT a denormalized num?
679 beq ta2, zero, result_fs_s # FT is zero, result=FS
680 subu t1, t1, SEXP_BIAS # unbias FS exponent
681 or t2, t2, SIMPL_ONE # set implied one bit
685 subu t1, t1, SEXP_BIAS # unbias FS exponent
686 or t2, t2, SIMPL_ONE # set implied one bit
687 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
688 or ta2, ta2, SIMPL_ONE # set implied one bit
690 * Perform the addition.
693 move t8, zero # no shifted bits (sticky reg)
694 beq t1, ta1, 4f # no shift needed
695 subu v0, t1, ta1 # v0 = difference of exponents
696 move v1, v0 # v1 = abs(difference)
700 ble v1, SFRAC_BITS+2, 2f # is difference too great?
701 li t8, STICKYBIT # set the sticky bit
702 bge v0, zero, 1f # check which exp is larger
703 move t1, ta1 # result exp is FTs
704 move t2, zero # FSs fraction shifted is zero
707 move ta2, zero # FTs fraction shifted is zero
710 li t9, 32 # compute 32 - abs(exp diff)
712 bgt v0, zero, 3f # if FS > FT, shift FTs frac
713 move t1, ta1 # FT > FS, result exp is FTs
714 sll t8, t2, t9 # save bits shifted out
715 srl t2, t2, v1 # shift FSs fraction
718 sll t8, ta2, t9 # save bits shifted out
719 srl ta2, ta2, v1 # shift FTs fraction
721 bne t0, ta0, 1f # if signs differ, subtract
722 addu t2, t2, ta2 # add fractions
725 blt t2, ta2, 3f # subtract larger from smaller
726 bne t2, ta2, 2f # if same, result=0
727 move t1, zero # result=0
729 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
730 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
731 or t0, t0, ta0 # compute result sign
734 and t0, t0, ta0 # compute result sign
737 sltu t9, zero, t8 # compute t2:zero - ta2:t8
739 subu t2, t2, ta2 # subtract fractions
740 subu t2, t2, t9 # subtract barrow
743 move t0, ta0 # sign of result = FTs
744 sltu t9, zero, t8 # compute ta2:zero - t2:t8
746 subu t2, ta2, t2 # subtract fractions
747 subu t2, t2, t9 # subtract barrow
751 * Double precision subtract.
755 xor ta0, ta0, 1 # negate sign bit
758 * Double precision add.
763 bne t1, DEXP_INF, 1f # is FS an infinity?
764 bne ta1, DEXP_INF, result_fs_d # if FT is not inf, result=FS
765 bne t2, zero, result_fs_d # if FS is NAN, result is FS
766 bne t3, zero, result_fs_d
767 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
768 bne ta3, zero, result_ft_d
769 bne t0, ta0, invalid_d # both infinities same sign?
770 b result_fs_d # result is in FS
772 beq ta1, DEXP_INF, result_ft_d # if FT is inf, result=FT
773 bne t1, zero, 4f # is FS a denormalized num?
774 bne t2, zero, 1f # is FS zero?
777 bne ta1, zero, 2f # is FT a denormalized num?
779 beq ta3, zero, result_fs_d # FT is zero, result=FS
786 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
787 or ta2, ta2, DIMPL_ONE # set implied one bit
790 bne ta1, zero, result_ft_d # if FT != 0, result=FT
791 bne ta2, zero, result_ft_d
792 bne ta3, zero, result_ft_d
793 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
794 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
795 or t0, t0, ta0 # compute result sign
798 and t0, t0, ta0 # compute result sign
801 bne ta1, zero, 2f # is FT a denormalized num?
803 beq ta3, zero, result_fs_d # FT is zero, result=FS
805 subu t1, t1, DEXP_BIAS # unbias FS exponent
806 or t2, t2, DIMPL_ONE # set implied one bit
810 subu t1, t1, DEXP_BIAS # unbias FS exponent
811 or t2, t2, DIMPL_ONE # set implied one bit
812 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
813 or ta2, ta2, DIMPL_ONE # set implied one bit
815 * Perform the addition.
818 move t8, zero # no shifted bits (sticky reg)
819 beq t1, ta1, 4f # no shift needed
820 subu v0, t1, ta1 # v0 = difference of exponents
821 move v1, v0 # v1 = abs(difference)
825 ble v1, DFRAC_BITS+2, 2f # is difference too great?
826 li t8, STICKYBIT # set the sticky bit
827 bge v0, zero, 1f # check which exp is larger
828 move t1, ta1 # result exp is FTs
829 move t2, zero # FSs fraction shifted is zero
833 move ta2, zero # FTs fraction shifted is zero
838 bge v0, zero, 3f # if FS > FT, shift FTs frac
839 move t1, ta1 # FT > FS, result exp is FTs
840 blt v1, t9, 1f # shift right by < 32?
843 sll t8, t2, t9 # save bits shifted out
844 sltu t9, zero, t3 # dont lose any one bits
845 or t8, t8, t9 # save sticky bit
846 srl t3, t2, v1 # shift FSs fraction
851 sll t8, t3, t9 # save bits shifted out
852 srl t3, t3, v1 # shift FSs fraction
853 sll t9, t2, t9 # save bits shifted out of t2
854 or t3, t3, t9 # and put into t3
858 blt v1, t9, 1f # shift right by < 32?
861 sll t8, ta2, t9 # save bits shifted out
862 srl ta3, ta2, v1 # shift FTs fraction
867 sll t8, ta3, t9 # save bits shifted out
868 srl ta3, ta3, v1 # shift FTs fraction
869 sll t9, ta2, t9 # save bits shifted out of t2
870 or ta3, ta3, t9 # and put into t3
873 bne t0, ta0, 1f # if signs differ, subtract
874 addu t3, t3, ta3 # add fractions
875 sltu t9, t3, ta3 # compute carry
876 addu t2, t2, ta2 # add fractions
877 addu t2, t2, t9 # add carry
880 blt t2, ta2, 3f # subtract larger from smaller
883 bne t3, ta3, 2f # if same, result=0
884 move t1, zero # result=0
887 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
888 bne v0, MIPS_FPU_ROUND_RM, 1f # round to -infinity?
889 or t0, t0, ta0 # compute result sign
892 and t0, t0, ta0 # compute result sign
895 beq t8, zero, 1f # compute t2:t3:zero - ta2:ta3:t8
897 sltu v0, t3, 1 # compute barrow out
898 subu t3, t3, 1 # subtract barrow
902 subu t3, t3, ta3 # subtract fractions
903 subu t2, t2, ta2 # subtract fractions
904 subu t2, t2, v0 # subtract barrow
907 move t0, ta0 # sign of result = FTs
908 beq t8, zero, 1f # compute ta2:ta3:zero - t2:t3:t8
910 sltu v0, ta3, 1 # compute barrow out
911 subu ta3, ta3, 1 # subtract barrow
915 subu t3, ta3, t3 # subtract fractions
916 subu t2, ta2, t2 # subtract fractions
917 subu t2, t2, v0 # subtract barrow
921 * Single precision multiply.
925 xor t0, t0, ta0 # compute sign of result
927 bne t1, SEXP_INF, 2f # is FS an infinity?
928 bne t2, zero, result_fs_s # if FS is a NAN, result=FS
929 bne ta1, SEXP_INF, 1f # FS is inf, is FT an infinity?
930 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
931 b result_fs_s # result is infinity
933 bne ta1, zero, result_fs_s # inf * zero? if no, result=FS
934 bne ta2, zero, result_fs_s
935 b invalid_s # infinity * zero is invalid
937 bne ta1, SEXP_INF, 1f # FS != inf, is FT an infinity?
938 bne t1, zero, result_ft_s # zero * inf? if no, result=FT
939 bne t2, zero, result_ft_s
940 bne ta2, zero, result_ft_s # if FT is a NAN, result=FT
941 b invalid_s # zero * infinity is invalid
943 bne t1, zero, 1f # is FS zero?
944 beq t2, zero, result_fs_s # result is zero
948 subu t1, t1, SEXP_BIAS # unbias FS exponent
949 or t2, t2, SIMPL_ONE # set implied one bit
951 bne ta1, zero, 1f # is FT zero?
952 beq ta2, zero, result_ft_s # result is zero
956 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
957 or ta2, ta2, SIMPL_ONE # set implied one bit
959 addu t1, t1, ta1 # compute result exponent
960 addu t1, t1, 9 # account for binary point
961 multu t2, ta2 # multiply fractions
967 * Double precision multiply.
971 xor t0, t0, ta0 # compute sign of result
973 bne t1, DEXP_INF, 2f # is FS an infinity?
974 bne t2, zero, result_fs_d # if FS is a NAN, result=FS
975 bne t3, zero, result_fs_d
976 bne ta1, DEXP_INF, 1f # FS is inf, is FT an infinity?
977 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
978 bne ta3, zero, result_ft_d
979 b result_fs_d # result is infinity
981 bne ta1, zero, result_fs_d # inf * zero? if no, result=FS
982 bne ta2, zero, result_fs_d
983 bne ta3, zero, result_fs_d
984 b invalid_d # infinity * zero is invalid
986 bne ta1, DEXP_INF, 1f # FS != inf, is FT an infinity?
987 bne t1, zero, result_ft_d # zero * inf? if no, result=FT
988 bne t2, zero, result_ft_d # if FS is a NAN, result=FS
989 bne t3, zero, result_ft_d
990 bne ta2, zero, result_ft_d # if FT is a NAN, result=FT
991 bne ta3, zero, result_ft_d
992 b invalid_d # zero * infinity is invalid
994 bne t1, zero, 2f # is FS zero?
996 beq t3, zero, result_fs_d # result is zero
1001 subu t1, t1, DEXP_BIAS # unbias FS exponent
1002 or t2, t2, DIMPL_ONE # set implied one bit
1004 bne ta1, zero, 2f # is FT zero?
1006 beq ta3, zero, result_ft_d # result is zero
1011 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
1012 or ta2, ta2, DIMPL_ONE # set implied one bit
1014 addu t1, t1, ta1 # compute result exponent
1015 addu t1, t1, 12 # ???
1016 multu t3, ta3 # multiply fractions (low * low)
1017 move ta0, t2 # free up t2,t3 for result
1019 mflo a3 # save low order bits
1022 multu ta0, ta3 # multiply FS(high) * FT(low)
1024 mfhi t3 # init low result
1025 sltu v0, v0, v1 # compute carry
1027 multu ta1, ta2 # multiply FS(low) * FT(high)
1028 addu t3, t3, v0 # add carry
1034 multu ta0, ta2 # multiply FS(high) * FT(high)
1046 sltu a3, zero, a3 # reduce t8,a3 to just t8
1051 * Single precision divide.
1055 xor t0, t0, ta0 # compute sign of result
1057 bne t1, SEXP_INF, 1f # is FS an infinity?
1058 bne t2, zero, result_fs_s # if FS is NAN, result is FS
1059 bne ta1, SEXP_INF, result_fs_s # is FT an infinity?
1060 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
1061 b invalid_s # infinity/infinity is invalid
1063 bne ta1, SEXP_INF, 1f # is FT an infinity?
1064 bne ta2, zero, result_ft_s # if FT is NAN, result is FT
1065 move t1, zero # x / infinity is zero
1069 bne t1, zero, 2f # is FS zero?
1071 bne ta1, zero, result_fs_s # FS=zero, is FT zero?
1072 beq ta2, zero, invalid_s # 0 / 0
1073 b result_fs_s # result = zero
1078 subu t1, t1, SEXP_BIAS # unbias FS exponent
1079 or t2, t2, SIMPL_ONE # set implied one bit
1081 bne ta1, zero, 2f # is FT zero?
1083 or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1084 and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled?
1085 bne v0, zero, fpe_trap
1086 ctc1 a1, MIPS_FPU_CSR # save exceptions
1087 li t1, SEXP_INF # result is infinity
1094 subu ta1, ta1, SEXP_BIAS # unbias FT exponent
1095 or ta2, ta2, SIMPL_ONE # set implied one bit
1097 subu t1, t1, ta1 # compute exponent
1098 subu t1, t1, 3 # compensate for result position
1099 li v0, SFRAC_BITS+3 # number of bits to divide
1100 move t8, t2 # init dividend
1101 move t2, zero # init result
1103 bltu t8, ta2, 3f # is dividend >= divisor?
1105 subu t8, t8, ta2 # subtract divisor from dividend
1106 or t2, t2, 1 # remember that we did
1107 bne t8, zero, 3f # if not done, continue
1108 sll t2, t2, v0 # shift result to final position
1111 sll t8, t8, 1 # shift dividend
1112 sll t2, t2, 1 # shift result
1113 subu v0, v0, 1 # are we done?
1114 bne v0, zero, 1b # no, continue
1118 * Double precision divide.
1122 xor t0, t0, ta0 # compute sign of result
1124 bne t1, DEXP_INF, 1f # is FS an infinity?
1125 bne t2, zero, result_fs_d # if FS is NAN, result is FS
1126 bne t3, zero, result_fs_d
1127 bne ta1, DEXP_INF, result_fs_d # is FT an infinity?
1128 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
1129 bne ta3, zero, result_ft_d
1130 b invalid_d # infinity/infinity is invalid
1132 bne ta1, DEXP_INF, 1f # is FT an infinity?
1133 bne ta2, zero, result_ft_d # if FT is NAN, result is FT
1134 bne ta3, zero, result_ft_d
1135 move t1, zero # x / infinity is zero
1140 bne t1, zero, 2f # is FS zero?
1143 bne ta1, zero, result_fs_d # FS=zero, is FT zero?
1144 bne ta2, zero, result_fs_d
1145 beq ta3, zero, invalid_d # 0 / 0
1146 b result_fs_d # result = zero
1151 subu t1, t1, DEXP_BIAS # unbias FS exponent
1152 or t2, t2, DIMPL_ONE # set implied one bit
1154 bne ta1, zero, 2f # is FT zero?
1157 or a1, a1, MIPS_FPU_EXCEPTION_DIV0 | MIPS_FPU_STICKY_DIV0
1158 and v0, a1, MIPS_FPU_ENABLE_DIV0 # trap enabled?
1159 bne v0, zero, fpe_trap
1160 ctc1 a1, MIPS_FPU_CSR # Save exceptions
1161 li t1, DEXP_INF # result is infinity
1169 subu ta1, ta1, DEXP_BIAS # unbias FT exponent
1170 or ta2, ta2, DIMPL_ONE # set implied one bit
1172 subu t1, t1, ta1 # compute exponent
1173 subu t1, t1, 3 # compensate for result position
1174 li v0, DFRAC_BITS+3 # number of bits to divide
1175 move t8, t2 # init dividend
1177 move t2, zero # init result
1180 bltu t8, ta2, 3f # is dividend >= divisor?
1184 sltu v1, t9, ta3 # subtract divisor from dividend
1188 or t3, t3, 1 # remember that we did
1189 bne t8, zero, 3f # if not done, continue
1191 li v1, 32 # shift result to final position
1192 blt v0, v1, 2f # shift < 32 bits?
1193 subu v0, v0, v1 # shift by > 32 bits
1194 sll t2, t3, v0 # shift upper part
1198 subu v1, v1, v0 # shift by < 32 bits
1199 sll t2, t2, v0 # shift upper part
1200 srl t9, t3, v1 # save bits shifted out
1201 or t2, t2, t9 # and put into upper part
1205 sll t8, t8, 1 # shift dividend
1206 srl v1, t9, 31 # save bit shifted out
1207 or t8, t8, v1 # and put into upper part
1209 sll t2, t2, 1 # shift result
1210 srl v1, t3, 31 # save bit shifted out
1211 or t2, t2, v1 # and put into upper part
1213 subu v0, v0, 1 # are we done?
1214 bne v0, zero, 1b # no, continue
1215 sltu v0, zero, t9 # be sure to save any one bits
1216 or t8, t8, v0 # from the lower remainder
1220 * Single precision absolute value.
1224 move t0, zero # set sign positive
1228 * Double precision absolute value.
1232 move t0, zero # set sign positive
1236 * Single precision move.
1243 * Double precision move.
1250 * Single precision negate.
1254 xor t0, t0, 1 # reverse sign
1258 * Double precision negate.
1262 xor t0, t0, 1 # reverse sign
1266 * Convert double to single.
1270 bne t1, DEXP_INF, 1f # is FS an infinity?
1271 li t1, SEXP_INF # convert to single
1272 sll t2, t2, 3 # convert D fraction to S
1277 bne t1, zero, 2f # is FS zero?
1279 beq t3, zero, result_fs_s # result=0
1282 subu t1, t1, 3 # correct exp for shift below
1285 subu t1, t1, DEXP_BIAS # unbias exponent
1286 or t2, t2, DIMPL_ONE # add implied one bit
1288 sll t2, t2, 3 # convert D fraction to S
1295 * Convert integer to single.
1299 bne t2, zero, 1f # check for zero
1303 * Find out how many leading zero bits are in t2 and put in t9.
1332 * Now shift t2 the correct number of bits.
1335 subu t9, t9, SLEAD_ZEROS # dont count leading zeros
1336 li t1, 23 # init exponent
1337 subu t1, t1, t9 # compute exponent
1340 blt t9, zero, 2f # if shift < 0, shift right
1342 sll t2, t2, t9 # shift left
1344 add t1, t1, SEXP_BIAS # bias exponent
1345 and t2, t2, ~SIMPL_ONE # clear implied one bit
1348 negu t9 # shift right by t9
1350 sll t8, t2, v0 # save bits shifted out
1355 * Convert single to double.
1360 bne t1, SEXP_INF, 1f # is FS an infinity?
1361 li t1, DEXP_INF # convert to double
1364 bne t1, zero, 2f # is FS denormalized or zero?
1365 beq t2, zero, result_fs_d # is FS zero?
1370 addu t1, t1, DEXP_BIAS - SEXP_BIAS # bias exponent correctly
1371 sll t3, t2, 32 - 3 # convert S fraction to D
1376 * Convert integer to double.
1380 bne t2, zero, 1f # check for zero
1381 move t1, zero # result=0
1385 * Find out how many leading zero bits are in t2 and put in t9.
1414 * Now shift t2 the correct number of bits.
1417 subu t9, t9, DLEAD_ZEROS # dont count leading zeros
1418 li t1, DEXP_BIAS + 20 # init exponent
1419 subu t1, t1, t9 # compute exponent
1422 blt t9, zero, 2f # if shift < 0, shift right
1424 sll t2, t2, t9 # shift left
1426 and t2, t2, ~DIMPL_ONE # clear implied one bit
1430 negu t9 # shift right by t9
1434 and t2, t2, ~DIMPL_ONE # clear implied one bit
1438 * Convert single to integer.
1442 bne t1, SEXP_INF, 1f # is FS an infinity?
1443 bne t2, zero, invalid_w # invalid conversion
1445 bne t1, zero, 1f # is FS zero?
1446 beq t2, zero, result_fs_w # result is zero
1447 move t2, zero # result is an inexact zero
1450 subu t1, t1, SEXP_BIAS # unbias exponent
1451 or t2, t2, SIMPL_ONE # add implied one bit
1452 sll t3, t2, 32 - 3 # convert S fraction to D
1457 * Convert double to integer.
1461 bne t1, DEXP_INF, 1f # is FS an infinity?
1462 bne t2, zero, invalid_w # invalid conversion
1463 bne t3, zero, invalid_w # invalid conversion
1465 bne t1, zero, 2f # is FS zero?
1467 beq t3, zero, result_fs_w # result is zero
1469 move t2, zero # result is an inexact zero
1472 subu t1, t1, DEXP_BIAS # unbias exponent
1473 or t2, t2, DIMPL_ONE # add implied one bit
1475 blt t1, WEXP_MIN, underflow_w # is exponent too small?
1477 bgt t1, v0, overflow_w # is exponent too large?
1478 bne t1, v0, 1f # special check for INT_MIN
1479 beq t0, zero, overflow_w # if positive, overflow
1480 bne t2, DIMPL_ONE, overflow_w
1481 bne t3, zero, overflow_w
1482 li t2, INT_MIN # result is INT_MIN
1485 subu v0, t1, 20 # compute amount to shift
1486 beq v0, zero, 2f # is shift needed?
1488 blt v0, zero, 1f # if shift < 0, shift right
1489 subu v1, v1, v0 # shift left
1491 srl t9, t3, v1 # save bits shifted out of t3
1492 or t2, t2, t9 # and put into t2
1493 sll t3, t3, v0 # shift FSs fraction
1496 negu v0 # shift right by v0
1498 sll t8, t3, v1 # save bits shifted out
1499 sltu t8, zero, t8 # dont lose any ones
1500 srl t3, t3, v0 # shift FSs fraction
1502 sll t9, t2, v1 # save bits shifted out of t2
1503 or t3, t3, t9 # and put into t3
1506 * round result (t0 is sign, t2 is integer part, t3 is fractional part).
1509 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1510 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1511 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1512 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1513 beq t0, zero, 5f # if sign is positive, truncate
1516 bne t0, zero, 5f # if sign is negative, truncate
1518 beq t3, zero, 5f # if no fraction bits, continue
1519 addu t2, t2, 1 # add rounding bit
1520 blt t2, zero, overflow_w # overflow?
1523 li v0, GUARDBIT # load guard bit for rounding
1524 addu v0, v0, t3 # add remainder
1525 sltu v1, v0, t3 # compute carry out
1526 beq v1, zero, 4f # if no carry, continue
1527 addu t2, t2, 1 # add carry to result
1528 blt t2, zero, overflow_w # overflow?
1530 bne v0, zero, 5f # if rounded remainder is zero
1531 and t2, t2, ~1 # clear LSB (round to nearest)
1533 beq t0, zero, 1f # result positive?
1534 negu t2 # convert to negative integer
1536 beq t3, zero, result_fs_w # is result exact?
1538 * Handle inexact exception.
1541 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1542 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1543 bne v0, zero, fpe_trap
1544 ctc1 a1, MIPS_FPU_CSR # save exceptions
1548 * Conversions to integer which overflow will trap (if enabled),
1549 * or generate an inexact trap (if enabled),
1550 * or generate an invalid exception.
1553 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1554 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1555 bne v0, zero, fpe_trap
1556 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1557 bne v0, zero, inexact_w # inexact traps enabled?
1561 * Conversions to integer which underflow will trap (if enabled),
1562 * or generate an inexact trap (if enabled),
1563 * or generate an invalid exception.
1566 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1567 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1568 bne v0, zero, fpe_trap
1569 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1570 bne v0, zero, inexact_w # inexact traps enabled?
1578 bne t1, SEXP_INF, 1f # is FS an infinity?
1579 bne t2, zero, unordered # FS is a NAN
1581 bne ta1, SEXP_INF, 2f # is FT an infinity?
1582 bne ta2, zero, unordered # FT is a NAN
1584 sll t1, t1, 23 # reassemble exp & frac
1586 sll ta1, ta1, 23 # reassemble exp & frac
1588 beq t0, zero, 1f # is FS positive?
1591 beq ta0, zero, 1f # is FT positive?
1595 blt t1, ta1, test_cond # is FS < FT?
1597 beq t1, ta1, test_cond # is FS == FT?
1598 move v0, zero # FS > FT
1606 bne t1, DEXP_INF, 1f # is FS an infinity?
1607 bne t2, zero, unordered
1608 bne t3, zero, unordered # FS is a NAN
1610 bne ta1, DEXP_INF, 2f # is FT an infinity?
1611 bne ta2, zero, unordered
1612 bne ta3, zero, unordered # FT is a NAN
1614 sll t1, t1, 20 # reassemble exp & frac
1616 sll ta1, ta1, 20 # reassemble exp & frac
1618 beq t0, zero, 1f # is FS positive?
1619 not t3 # negate t1,t3
1622 seq v0, t3, zero # compute carry
1625 beq ta0, zero, 1f # is FT positive?
1626 not ta3 # negate ta1,ta3
1629 seq v0, ta3, zero # compute carry
1633 blt t1, ta1, test_cond # is FS(MSW) < FT(MSW)?
1635 bne t1, ta1, test_cond # is FS(MSW) > FT(MSW)?
1637 bltu t3, ta3, test_cond # is FS(LSW) < FT(LSW)?
1639 beq t3, ta3, test_cond # is FS(LSW) == FT(LSW)?
1640 move v0, zero # FS > FT
1642 and v0, v0, a0 # condition match instruction?
1645 and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit
1648 or a1, a1, MIPS_FPU_COND_BIT # set condition bit
1650 ctc1 a1, MIPS_FPU_CSR # save condition bit
1654 and v0, a0, COND_UNORDERED # this cmp match unordered?
1656 and a1, a1, ~MIPS_FPU_COND_BIT # clear condition bit
1659 or a1, a1, MIPS_FPU_COND_BIT # set condition bit
1661 and v0, a0, COND_SIGNAL
1662 beq v0, zero, 1f # is this a signaling cmp?
1663 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
1664 and v0, a1, MIPS_FPU_ENABLE_INVALID
1665 bne v0, zero, fpe_trap
1667 ctc1 a1, MIPS_FPU_CSR # save condition bit
1671 * Determine the amount to shift the fraction in order to restore the
1672 * normalized position. After that, round and handle exceptions.
1676 move t9, zero # t9 = num of leading zeros
1705 * Now shift t2,t8 the correct number of bits.
1708 subu t9, t9, SLEAD_ZEROS # dont count leading zeros
1709 subu t1, t1, t9 # adjust the exponent
1710 beq t9, zero, norm_noshift_s
1712 blt t9, zero, 1f # if shift < 0, shift right
1714 sll t2, t2, t9 # shift t2,t8 left
1715 srl v0, t8, v1 # save bits shifted out
1720 negu t9 # shift t2,t8 right by t9
1722 sll v0, t8, v1 # save bits shifted out
1723 sltu v0, zero, v0 # be sure to save any one bits
1726 sll v0, t2, v1 # save bits shifted out
1730 move ta1, t1 # save unrounded exponent
1731 move ta2, t2 # save unrounded fraction
1732 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1733 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1734 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1735 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1736 beq t0, zero, 5f # if sign is positive, truncate
1739 bne t0, zero, 5f # if sign is negative, truncate
1741 beq t8, zero, 5f # if exact, continue
1742 addu t2, t2, 1 # add rounding bit
1743 bne t2, SIMPL_ONE<<1, 5f # need to adjust exponent?
1744 addu t1, t1, 1 # adjust exponent
1745 srl t2, t2, 1 # renormalize fraction
1748 li v0, GUARDBIT # load guard bit for rounding
1749 addu v0, v0, t8 # add remainder
1750 sltu v1, v0, t8 # compute carry out
1751 beq v1, zero, 4f # if no carry, continue
1752 addu t2, t2, 1 # add carry to result
1753 bne t2, SIMPL_ONE<<1, 4f # need to adjust exponent?
1754 addu t1, t1, 1 # adjust exponent
1755 srl t2, t2, 1 # renormalize fraction
1757 bne v0, zero, 5f # if rounded remainder is zero
1758 and t2, t2, ~1 # clear LSB (round to nearest)
1760 bgt t1, SEXP_MAX, overflow_s # overflow?
1761 blt t1, SEXP_MIN, underflow_s # underflow?
1762 bne t8, zero, inexact_s # is result inexact?
1763 addu t1, t1, SEXP_BIAS # bias exponent
1764 and t2, t2, ~SIMPL_ONE # clear implied one bit
1768 * Handle inexact exception.
1771 addu t1, t1, SEXP_BIAS # bias exponent
1772 and t2, t2, ~SIMPL_ONE # clear implied one bit
1774 jal set_fd_s # save result
1775 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1776 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1777 bne v0, zero, fpe_trap
1778 ctc1 a1, MIPS_FPU_CSR # save exceptions
1782 * Overflow will trap (if enabled),
1783 * or generate an inexact trap (if enabled),
1784 * or generate an infinity.
1787 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
1788 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
1790 subu t1, t1, 192 # bias exponent
1791 and t2, t2, ~SIMPL_ONE # clear implied one bit
1792 jal set_fd_s # save result
1795 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1796 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1797 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate)
1798 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity
1801 li t1, SEXP_MAX # result is max finite
1807 li t1, SEXP_MAX + 1 # result is infinity
1812 * In this implementation, "tininess" is detected "after rounding" and
1813 * "loss of accuracy" is detected as "an inexact result".
1816 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
1819 * Underflow is enabled so compute the result and trap.
1821 addu t1, t1, 192 # bias exponent
1822 and t2, t2, ~SIMPL_ONE # clear implied one bit
1823 jal set_fd_s # save result
1824 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1827 * Underflow is not enabled so compute the result,
1828 * signal inexact result (if it is) and trap (if enabled).
1831 move t1, ta1 # get unrounded exponent
1832 move t2, ta2 # get unrounded fraction
1833 li t9, SEXP_MIN # compute shift amount
1834 subu t9, t9, t1 # shift t2,t8 right by t9
1835 blt t9, SFRAC_BITS+2, 3f # shift all the bits out?
1836 move t1, zero # result is inexact zero
1838 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1840 * Now round the zero result.
1841 * Only need to worry about rounding to +- infinity when the sign matches.
1843 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1844 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_s # round to nearest
1845 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_s # round to zero
1846 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1847 beq t0, zero, inexact_nobias_s # if sign is positive, truncate
1850 bne t0, zero, inexact_nobias_s # if sign is negative, truncate
1852 addu t2, t2, 1 # add rounding bit
1857 sltu v0, zero, t8 # be sure to save any one bits
1858 sll t8, t2, v1 # save bits shifted out
1859 or t8, t8, v0 # include sticky bits
1862 * Now round the denormalized result.
1864 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1865 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1866 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1867 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1868 beq t0, zero, 5f # if sign is positive, truncate
1871 bne t0, zero, 5f # if sign is negative, truncate
1873 beq t8, zero, 5f # if exact, continue
1874 addu t2, t2, 1 # add rounding bit
1877 li v0, GUARDBIT # load guard bit for rounding
1878 addu v0, v0, t8 # add remainder
1879 sltu v1, v0, t8 # compute carry out
1880 beq v1, zero, 4f # if no carry, continue
1881 addu t2, t2, 1 # add carry to result
1883 bne v0, zero, 5f # if rounded remainder is zero
1884 and t2, t2, ~1 # clear LSB (round to nearest)
1886 move t1, zero # denorm or zero exponent
1887 jal set_fd_s # save result
1888 beq t8, zero, done # check for exact result
1889 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
1890 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
1891 and v0, a1, MIPS_FPU_ENABLE_INEXACT
1892 bne v0, zero, fpe_trap
1893 ctc1 a1, MIPS_FPU_CSR # save exceptions
1897 * Determine the amount to shift the fraction in order to restore the
1898 * normalized position. After that, round and handle exceptions.
1902 move t9, zero # t9 = num of leading zeros
1934 * Now shift t2,t3,t8 the correct number of bits.
1937 subu t9, t9, DLEAD_ZEROS # dont count leading zeros
1938 subu t1, t1, t9 # adjust the exponent
1939 beq t9, zero, norm_noshift_d
1941 blt t9, zero, 2f # if shift < 0, shift right
1942 blt t9, v1, 1f # shift by < 32?
1943 subu t9, t9, v1 # shift by >= 32
1945 sll t2, t3, t9 # shift left by t9
1946 srl v0, t8, v1 # save bits shifted out
1953 sll t2, t2, t9 # shift left by t9
1954 srl v0, t3, v1 # save bits shifted out
1957 srl v0, t8, v1 # save bits shifted out
1962 negu t9 # shift right by t9
1963 subu v1, v1, t9 # (known to be < 32 bits)
1964 sll v0, t8, v1 # save bits shifted out
1965 sltu v0, zero, v0 # be sure to save any one bits
1968 sll v0, t3, v1 # save bits shifted out
1971 sll v0, t2, v1 # save bits shifted out
1975 move ta1, t1 # save unrounded exponent
1976 move ta2, t2 # save unrounded fraction (MS)
1977 move ta3, t3 # save unrounded fraction (LS)
1978 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
1979 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
1980 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
1981 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
1982 beq t0, zero, 5f # if sign is positive, truncate
1985 bne t0, zero, 5f # if sign is negative, truncate
1987 beq t8, zero, 5f # if exact, continue
1988 addu t3, t3, 1 # add rounding bit
1989 bne t3, zero, 5f # branch if no carry
1990 addu t2, t2, 1 # add carry
1991 bne t2, DIMPL_ONE<<1, 5f # need to adjust exponent?
1992 addu t1, t1, 1 # adjust exponent
1993 srl t2, t2, 1 # renormalize fraction
1996 li v0, GUARDBIT # load guard bit for rounding
1997 addu v0, v0, t8 # add remainder
1998 sltu v1, v0, t8 # compute carry out
1999 beq v1, zero, 4f # branch if no carry
2000 addu t3, t3, 1 # add carry
2001 bne t3, zero, 4f # branch if no carry
2002 addu t2, t2, 1 # add carry to result
2003 bne t2, DIMPL_ONE<<1, 4f # need to adjust exponent?
2004 addu t1, t1, 1 # adjust exponent
2005 srl t2, t2, 1 # renormalize fraction
2007 bne v0, zero, 5f # if rounded remainder is zero
2008 and t3, t3, ~1 # clear LSB (round to nearest)
2010 bgt t1, DEXP_MAX, overflow_d # overflow?
2011 blt t1, DEXP_MIN, underflow_d # underflow?
2012 bne t8, zero, inexact_d # is result inexact?
2013 addu t1, t1, DEXP_BIAS # bias exponent
2014 and t2, t2, ~DIMPL_ONE # clear implied one bit
2018 * Handle inexact exception.
2021 addu t1, t1, DEXP_BIAS # bias exponent
2022 and t2, t2, ~DIMPL_ONE # clear implied one bit
2024 jal set_fd_d # save result
2025 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2026 and v0, a1, MIPS_FPU_ENABLE_INEXACT
2027 bne v0, zero, fpe_trap
2028 ctc1 a1, MIPS_FPU_CSR # save exceptions
2032 * Overflow will trap (if enabled),
2033 * or generate an inexact trap (if enabled),
2034 * or generate an infinity.
2037 or a1, a1, MIPS_FPU_EXCEPTION_OVERFLOW | MIPS_FPU_STICKY_OVERFLOW
2038 and v0, a1, MIPS_FPU_ENABLE_OVERFLOW
2040 subu t1, t1, 1536 # bias exponent
2041 and t2, t2, ~DIMPL_ONE # clear implied one bit
2042 jal set_fd_d # save result
2045 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
2046 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
2047 beq v0, MIPS_FPU_ROUND_RZ, 1f # round to zero (truncate)
2048 beq v0, MIPS_FPU_ROUND_RP, 2f # round to +infinity
2051 li t1, DEXP_MAX # result is max finite
2058 li t1, DEXP_MAX + 1 # result is infinity
2064 * In this implementation, "tininess" is detected "after rounding" and
2065 * "loss of accuracy" is detected as "an inexact result".
2068 and v0, a1, MIPS_FPU_ENABLE_UNDERFLOW
2071 * Underflow is enabled so compute the result and trap.
2073 addu t1, t1, 1536 # bias exponent
2074 and t2, t2, ~DIMPL_ONE # clear implied one bit
2075 jal set_fd_d # save result
2076 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2079 * Underflow is not enabled so compute the result,
2080 * signal inexact result (if it is) and trap (if enabled).
2083 move t1, ta1 # get unrounded exponent
2084 move t2, ta2 # get unrounded fraction (MS)
2085 move t3, ta3 # get unrounded fraction (LS)
2086 li t9, DEXP_MIN # compute shift amount
2087 subu t9, t9, t1 # shift t2,t8 right by t9
2088 blt t9, DFRAC_BITS+2, 3f # shift all the bits out?
2089 move t1, zero # result is inexact zero
2092 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2094 * Now round the zero result.
2095 * Only need to worry about rounding to +- infinity when the sign matches.
2097 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
2098 beq v0, MIPS_FPU_ROUND_RN, inexact_nobias_d # round to nearest
2099 beq v0, MIPS_FPU_ROUND_RZ, inexact_nobias_d # round to zero
2100 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
2101 beq t0, zero, inexact_nobias_d # if sign is positive, truncate
2104 bne t0, zero, inexact_nobias_d # if sign is negative, truncate
2106 addu t3, t3, 1 # add rounding bit
2110 blt t9, v1, 1f # shift by < 32?
2111 subu t9, t9, v1 # shift right by >= 32
2113 sltu v0, zero, t8 # be sure to save any one bits
2114 sll t8, t2, v1 # save bits shifted out
2115 or t8, t8, v0 # include sticky bits
2120 subu v1, v1, t9 # shift right by t9
2121 sltu v0, zero, t8 # be sure to save any one bits
2122 sll t8, t3, v1 # save bits shifted out
2123 or t8, t8, v0 # include sticky bits
2125 sll v0, t2, v1 # save bits shifted out
2129 * Now round the denormalized result.
2132 and v0, a1, MIPS_FPU_ROUNDING_BITS # get rounding mode
2133 beq v0, MIPS_FPU_ROUND_RN, 3f # round to nearest
2134 beq v0, MIPS_FPU_ROUND_RZ, 5f # round to zero (truncate)
2135 beq v0, MIPS_FPU_ROUND_RP, 1f # round to +infinity
2136 beq t0, zero, 5f # if sign is positive, truncate
2139 bne t0, zero, 5f # if sign is negative, truncate
2141 beq t8, zero, 5f # if exact, continue
2142 addu t3, t3, 1 # add rounding bit
2143 bne t3, zero, 5f # if no carry, continue
2144 addu t2, t2, 1 # add carry
2147 li v0, GUARDBIT # load guard bit for rounding
2148 addu v0, v0, t8 # add remainder
2149 sltu v1, v0, t8 # compute carry out
2150 beq v1, zero, 4f # if no carry, continue
2151 addu t3, t3, 1 # add rounding bit
2152 bne t3, zero, 4f # if no carry, continue
2153 addu t2, t2, 1 # add carry
2155 bne v0, zero, 5f # if rounded remainder is zero
2156 and t3, t3, ~1 # clear LSB (round to nearest)
2158 move t1, zero # denorm or zero exponent
2159 jal set_fd_d # save result
2160 beq t8, zero, done # check for exact result
2161 or a1, a1, MIPS_FPU_EXCEPTION_UNDERFLOW | MIPS_FPU_STICKY_UNDERFLOW
2162 or a1, a1, MIPS_FPU_EXCEPTION_INEXACT | MIPS_FPU_STICKY_INEXACT
2163 and v0, a1, MIPS_FPU_ENABLE_INEXACT
2164 bne v0, zero, fpe_trap
2165 ctc1 a1, MIPS_FPU_CSR # save exceptions
2169 * Signal an invalid operation if the trap is enabled; otherwise,
2170 * the result is a quiet NAN.
2172 invalid_s: # trap invalid operation
2173 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2174 and v0, a1, MIPS_FPU_ENABLE_INVALID
2175 bne v0, zero, fpe_trap
2176 ctc1 a1, MIPS_FPU_CSR # save exceptions
2177 move t0, zero # result is a quiet NAN
2180 jal set_fd_s # save result (in t0,t1,t2)
2184 * Signal an invalid operation if the trap is enabled; otherwise,
2185 * the result is a quiet NAN.
2187 invalid_d: # trap invalid operation
2188 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2189 and v0, a1, MIPS_FPU_ENABLE_INVALID
2190 bne v0, zero, fpe_trap
2191 ctc1 a1, MIPS_FPU_CSR # save exceptions
2192 move t0, zero # result is a quiet NAN
2196 jal set_fd_d # save result (in t0,t1,t2,t3)
2200 * Signal an invalid operation if the trap is enabled; otherwise,
2201 * the result is INT_MAX or INT_MIN.
2203 invalid_w: # trap invalid operation
2204 or a1, a1, MIPS_FPU_EXCEPTION_INVALID | MIPS_FPU_STICKY_INVALID
2205 and v0, a1, MIPS_FPU_ENABLE_INVALID
2206 bne v0, zero, fpe_trap
2207 ctc1 a1, MIPS_FPU_CSR # save exceptions
2209 li t2, INT_MAX # result is INT_MAX
2212 li t2, INT_MIN # result is INT_MIN
2216 * Trap if the hardware should have handled this case.
2219 move a2, a1 # code = FP CSR
2220 ctc1 a1, MIPS_FPU_CSR # save exceptions
2224 * Send an illegal instruction signal to the current process.
2227 ctc1 a1, MIPS_FPU_CSR # save exceptions
2228 move a2, a0 # code = FP instruction
2232 move t0, ta0 # result is FT
2235 result_fs_s: # result is FS
2236 jal set_fd_s # save result (in t0,t1,t2)
2240 jal set_fd_word # save result (in t2)
2244 move t0, ta0 # result is FT
2248 result_fs_d: # result is FS
2249 jal set_fd_d # save result (in t0,t1,t2,t3)
2252 lw ra, CALLFRAME_RA(sp)
2253 addu sp, sp, CALLFRAME_SIZ
2257 /*----------------------------------------------------------------------------
2260 * Read (integer) the FS register (bits 15-11).
2261 * This is an internal routine used by MipsEmulateFP only.
2264 * t0 contains the sign
2265 * t2 contains the fraction
2267 *----------------------------------------------------------------------------
2270 srl a3, a0, 12 - 2 # get FS field (even regs only)
2271 and a3, a3, 0xF << 2 # mask FS field
2272 lw a3, get_fs_int_tbl(a3) # switch on register number
2282 .word get_fs_int_f10
2283 .word get_fs_int_f12
2284 .word get_fs_int_f14
2285 .word get_fs_int_f16
2286 .word get_fs_int_f18
2287 .word get_fs_int_f20
2288 .word get_fs_int_f22
2289 .word get_fs_int_f24
2290 .word get_fs_int_f26
2291 .word get_fs_int_f28
2292 .word get_fs_int_f30
2343 srl t0, t2, 31 # init the sign bit
2350 /*----------------------------------------------------------------------------
2353 * Read (single precision) the FT register (bits 20-16) and
2354 * the FS register (bits 15-11) and break up into fields.
2355 * This is an internal routine used by MipsEmulateFP only.
2358 * t0 contains the FS sign
2359 * t1 contains the FS (biased) exponent
2360 * t2 contains the FS fraction
2361 * ta0 contains the FT sign
2362 * ta1 contains the FT (biased) exponent
2363 * ta2 contains the FT fraction
2365 *----------------------------------------------------------------------------
2368 srl a3, a0, 17 - 2 # get FT field (even regs only)
2369 and a3, a3, 0xF << 2 # mask FT field
2370 lw a3, get_ft_s_tbl(a3) # switch on register number
2441 srl ta1, ta0, 23 # get exponent
2443 and ta2, ta0, 0x7FFFFF # get fraction
2444 srl ta0, ta0, 31 # get sign
2445 bne ta1, SEXP_INF, 1f # is it a signaling NAN?
2446 and v0, ta2, SSIGNAL_NAN
2447 bne v0, zero, invalid_s
2449 /* fall through to get FS */
2451 /*----------------------------------------------------------------------------
2454 * Read (single precision) the FS register (bits 15-11) and
2455 * break up into fields.
2456 * This is an internal routine used by MipsEmulateFP only.
2459 * t0 contains the sign
2460 * t1 contains the (biased) exponent
2461 * t2 contains the fraction
2463 *----------------------------------------------------------------------------
2466 srl a3, a0, 12 - 2 # get FS field (even regs only)
2467 and a3, a3, 0xF << 2 # mask FS field
2468 lw a3, get_fs_s_tbl(a3) # switch on register number
2539 srl t1, t0, 23 # get exponent
2541 and t2, t0, 0x7FFFFF # get fraction
2542 srl t0, t0, 31 # get sign
2543 bne t1, SEXP_INF, 1f # is it a signaling NAN?
2544 and v0, t2, SSIGNAL_NAN
2545 bne v0, zero, invalid_s
2550 /*----------------------------------------------------------------------------
2553 * Read (double precision) the FT register (bits 20-16) and
2554 * the FS register (bits 15-11) and break up into fields.
2555 * This is an internal routine used by MipsEmulateFP only.
2558 * t0 contains the FS sign
2559 * t1 contains the FS (biased) exponent
2560 * t2 contains the FS fraction
2561 * t3 contains the FS remaining fraction
2562 * ta0 contains the FT sign
2563 * ta1 contains the FT (biased) exponent
2564 * ta2 contains the FT fraction
2565 * ta3 contains the FT remaining fraction
2567 *----------------------------------------------------------------------------
2570 srl a3, a0, 17 - 2 # get FT field (even regs only)
2571 and a3, a3, 0xF << 2 # mask FT field
2572 lw a3, get_ft_d_tbl(a3) # switch on register number
2659 srl ta1, ta0, 20 # get exponent
2661 and ta2, ta0, 0xFFFFF # get fraction
2662 srl ta0, ta0, 31 # get sign
2663 bne ta1, DEXP_INF, 1f # is it a signaling NAN?
2664 and v0, ta2, DSIGNAL_NAN
2665 bne v0, zero, invalid_d
2667 /* fall through to get FS */
2669 /*----------------------------------------------------------------------------
2672 * Read (double precision) the FS register (bits 15-11) and
2673 * break up into fields.
2674 * This is an internal routine used by MipsEmulateFP only.
2677 * t0 contains the sign
2678 * t1 contains the (biased) exponent
2679 * t2 contains the fraction
2680 * t3 contains the remaining fraction
2682 *----------------------------------------------------------------------------
2685 srl a3, a0, 12 - 2 # get FS field (even regs only)
2686 and a3, a3, 0xF << 2 # mask FS field
2687 lw a3, get_fs_d_tbl(a3) # switch on register number
2774 srl t1, t0, 20 # get exponent
2776 and t2, t0, 0xFFFFF # get fraction
2777 srl t0, t0, 31 # get sign
2778 bne t1, DEXP_INF, 1f # is it a signaling NAN?
2779 and v0, t2, DSIGNAL_NAN
2780 bne v0, zero, invalid_d
2785 /*----------------------------------------------------------------------------
2788 * Read (single precision) the FS register (bits 15-11) and
2789 * the FT register (bits 20-16) and break up into fields.
2790 * This is an internal routine used by MipsEmulateFP only.
2793 * t0 contains the sign
2794 * t1 contains the (biased) exponent
2795 * t2 contains the fraction
2796 * ta0 contains the sign
2797 * ta1 contains the (biased) exponent
2798 * ta2 contains the fraction
2800 *----------------------------------------------------------------------------
2803 srl a3, a0, 12 - 2 # get FS field (even regs only)
2804 and a3, a3, 0xF << 2 # mask FS field
2805 lw a3, cmp_fs_s_tbl(a3) # switch on register number
2876 srl t1, t0, 23 # get exponent
2878 and t2, t0, 0x7FFFFF # get fraction
2879 srl t0, t0, 31 # get sign
2881 srl a3, a0, 17 - 2 # get FT field (even regs only)
2882 and a3, a3, 0xF << 2 # mask FT field
2883 lw a3, cmp_ft_s_tbl(a3) # switch on register number
2954 srl ta1, ta0, 23 # get exponent
2956 and ta2, ta0, 0x7FFFFF # get fraction
2957 srl ta0, ta0, 31 # get sign
2961 /*----------------------------------------------------------------------------
2964 * Read (double precision) the FS register (bits 15-11) and
2965 * the FT register (bits 20-16) and break up into fields.
2966 * This is an internal routine used by MipsEmulateFP only.
2969 * t0 contains the sign
2970 * t1 contains the (biased) exponent
2971 * t2 contains the fraction
2972 * t3 contains the remaining fraction
2973 * ta0 contains the sign
2974 * ta1 contains the (biased) exponent
2975 * ta2 contains the fraction
2976 * ta3 contains the remaining fraction
2978 *----------------------------------------------------------------------------
2981 srl a3, a0, 12 - 2 # get FS field (even regs only)
2982 and a3, a3, 0xF << 2 # mask FS field
2983 lw a3, cmp_fs_d_tbl(a3) # switch on register number
3070 srl t1, t0, 20 # get exponent
3072 and t2, t0, 0xFFFFF # get fraction
3073 srl t0, t0, 31 # get sign
3075 srl a3, a0, 17 - 2 # get FT field (even regs only)
3076 and a3, a3, 0xF << 2 # mask FT field
3077 lw a3, cmp_ft_d_tbl(a3) # switch on register number
3164 srl ta1, ta0, 20 # get exponent
3166 and ta2, ta0, 0xFFFFF # get fraction
3167 srl ta0, ta0, 31 # get sign
3171 /*----------------------------------------------------------------------------
3174 * Write (single precision) the FD register (bits 10-6).
3175 * This is an internal routine used by MipsEmulateFP only.
3178 * a0 contains the FP instruction
3179 * t0 contains the sign
3180 * t1 contains the (biased) exponent
3181 * t2 contains the fraction
3185 * Write (integer) the FD register (bits 10-6).
3186 * This is an internal routine used by MipsEmulateFP only.
3189 * a0 contains the FP instruction
3190 * t2 contains the integer
3192 *----------------------------------------------------------------------------
3195 sll t0, t0, 31 # position sign
3196 sll t1, t1, 23 # position exponent
3200 srl a3, a0, 7 - 2 # get FD field (even regs only)
3201 and a3, a3, 0xF << 2 # mask FT field
3202 lw a3, set_fd_s_tbl(a3) # switch on register number
3275 /*----------------------------------------------------------------------------
3278 * Write (double precision) the FT register (bits 10-6).
3279 * This is an internal routine used by MipsEmulateFP only.
3282 * a0 contains the FP instruction
3283 * t0 contains the sign
3284 * t1 contains the (biased) exponent
3285 * t2 contains the fraction
3286 * t3 contains the remaining fraction
3288 *----------------------------------------------------------------------------
3291 sll t0, t0, 31 # set sign
3292 sll t1, t1, 20 # set exponent
3294 or t0, t0, t2 # set fraction
3295 srl a3, a0, 7 - 2 # get FD field (even regs only)
3296 and a3, a3, 0xF << 2 # mask FD field
3297 lw a3, set_fd_d_tbl(a3) # switch on register number
3386 /*----------------------------------------------------------------------------
3390 * t1 unbiased exponent
3391 * t2 normalized fraction
3393 *----------------------------------------------------------------------------
3397 * Find out how many leading zero bits are in t2 and put in t9.
3425 * Now shift t2 the correct number of bits.
3428 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
3430 subu t1, t1, t9 # adjust exponent
3435 /*----------------------------------------------------------------------------
3439 * t1 unbiased exponent
3440 * t2,t3 normalized fraction
3442 *----------------------------------------------------------------------------
3446 * Find out how many leading zero bits are in t2,t3 and put in t9.
3478 * Now shift t2,t3 the correct number of bits.
3481 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
3483 subu t1, t1, t9 # adjust exponent
3486 subu t9, t9, v0 # shift fraction left >= 32 bits
3491 subu v0, v0, t9 # shift fraction left < 32 bits
3499 /*----------------------------------------------------------------------------
3503 * ta1 unbiased exponent
3504 * ta2 normalized fraction
3506 *----------------------------------------------------------------------------
3510 * Find out how many leading zero bits are in ta2 and put in t9.
3538 * Now shift ta2 the correct number of bits.
3541 subu t9, t9, SLEAD_ZEROS # dont count normal leading zeros
3543 subu ta1, ta1, t9 # adjust exponent
3548 /*----------------------------------------------------------------------------
3552 * ta1 unbiased exponent
3553 * ta2,ta3 normalized fraction
3555 *----------------------------------------------------------------------------
3559 * Find out how many leading zero bits are in ta2,ta3 and put in t9.
3591 * Now shift ta2,ta3 the correct number of bits.
3594 subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
3596 subu ta1, ta1, t9 # adjust exponent
3599 subu t9, t9, v0 # shift fraction left >= 32 bits
3604 subu v0, v0, t9 # shift fraction left < 32 bits