Commit 8dfdb87c8d675b846e12c8066922525e22bcfc50
1 parent
d79acba4
Implement recip1/recip2/rsqrt1/rsqrt2.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3026 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
143 additions
and
93 deletions
target-mips/op_helper.c
@@ -597,6 +597,13 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) | @@ -597,6 +597,13 @@ void tlb_fill (target_ulong addr, int is_write, int is_user, void *retaddr) | ||
597 | 597 | ||
598 | /* Complex FPU operations which may need stack space. */ | 598 | /* Complex FPU operations which may need stack space. */ |
599 | 599 | ||
600 | +#define FLOAT_SIGN32 (1 << 31) | ||
601 | +#define FLOAT_SIGN64 (1ULL << 63) | ||
602 | +#define FLOAT_ONE32 (0x3f8 << 20) | ||
603 | +#define FLOAT_ONE64 (0x3ffULL << 52) | ||
604 | +#define FLOAT_TWO32 (1 << 30) | ||
605 | +#define FLOAT_TWO64 (1ULL << 62) | ||
606 | + | ||
600 | /* convert MIPS rounding mode in FCR31 to IEEE library */ | 607 | /* convert MIPS rounding mode in FCR31 to IEEE library */ |
601 | unsigned int ieee_rm[] = { | 608 | unsigned int ieee_rm[] = { |
602 | float_round_nearest_even, | 609 | float_round_nearest_even, |
@@ -912,58 +919,78 @@ FLOAT_OP(floorw, s) | @@ -912,58 +919,78 @@ FLOAT_OP(floorw, s) | ||
912 | WT2 = 0x7fffffff; | 919 | WT2 = 0x7fffffff; |
913 | } | 920 | } |
914 | 921 | ||
915 | -/* unary operations, MIPS specific, s and d */ | ||
916 | -#define FLOAT_UNOP(name) \ | ||
917 | -FLOAT_OP(name, d) \ | ||
918 | -{ \ | ||
919 | - set_float_exception_flags(0, &env->fp_status); \ | ||
920 | -/* XXX: not implemented */ \ | ||
921 | -/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \ | ||
922 | -do_raise_exception(EXCP_RI); \ | ||
923 | - update_fcr31(); \ | ||
924 | -} \ | ||
925 | -FLOAT_OP(name, s) \ | ||
926 | -{ \ | ||
927 | - set_float_exception_flags(0, &env->fp_status); \ | ||
928 | -/* XXX: not implemented */ \ | ||
929 | -/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \ | ||
930 | -do_raise_exception(EXCP_RI); \ | ||
931 | - update_fcr31(); \ | 922 | +/* MIPS specific unary operations */ |
923 | +FLOAT_OP(recip, d) | ||
924 | +{ | ||
925 | + set_float_exception_flags(0, &env->fp_status); | ||
926 | + FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status); | ||
927 | + update_fcr31(); | ||
928 | +} | ||
929 | +FLOAT_OP(recip, s) | ||
930 | +{ | ||
931 | + set_float_exception_flags(0, &env->fp_status); | ||
932 | + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); | ||
933 | + update_fcr31(); | ||
932 | } | 934 | } |
933 | -FLOAT_UNOP(rsqrt) | ||
934 | -FLOAT_UNOP(recip) | ||
935 | -#undef FLOAT_UNOP | ||
936 | 935 | ||
937 | -/* unary operations, MIPS specific, s, d and ps */ | ||
938 | -#define FLOAT_UNOP(name) \ | ||
939 | -FLOAT_OP(name, d) \ | ||
940 | -{ \ | ||
941 | - set_float_exception_flags(0, &env->fp_status); \ | ||
942 | -/* XXX: not implemented */ \ | ||
943 | -/* FDT2 = float64_ ## name (FDT0, &env->fp_status);*/ \ | ||
944 | -do_raise_exception(EXCP_RI); \ | ||
945 | - update_fcr31(); \ | ||
946 | -} \ | ||
947 | -FLOAT_OP(name, s) \ | ||
948 | -{ \ | ||
949 | - set_float_exception_flags(0, &env->fp_status); \ | ||
950 | -/* XXX: not implemented */ \ | ||
951 | -/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \ | ||
952 | -do_raise_exception(EXCP_RI); \ | ||
953 | - update_fcr31(); \ | ||
954 | -} \ | ||
955 | -FLOAT_OP(name, ps) \ | ||
956 | -{ \ | ||
957 | - set_float_exception_flags(0, &env->fp_status); \ | ||
958 | -/* XXX: not implemented */ \ | ||
959 | -/* FST2 = float32_ ## name (FST0, &env->fp_status);*/ \ | ||
960 | -/* FSTH2 = float32_ ## name (FSTH0, &env->fp_status);*/ \ | ||
961 | -do_raise_exception(EXCP_RI); \ | ||
962 | - update_fcr31(); \ | 936 | +FLOAT_OP(rsqrt, d) |
937 | +{ | ||
938 | + set_float_exception_flags(0, &env->fp_status); | ||
939 | + FDT2 = float64_sqrt(FDT0, &env->fp_status); | ||
940 | + FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status); | ||
941 | + update_fcr31(); | ||
942 | +} | ||
943 | +FLOAT_OP(rsqrt, s) | ||
944 | +{ | ||
945 | + set_float_exception_flags(0, &env->fp_status); | ||
946 | + FST2 = float32_sqrt(FST0, &env->fp_status); | ||
947 | + FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status); | ||
948 | + update_fcr31(); | ||
949 | +} | ||
950 | + | ||
951 | +FLOAT_OP(recip1, d) | ||
952 | +{ | ||
953 | + set_float_exception_flags(0, &env->fp_status); | ||
954 | + FDT2 = float64_div(FLOAT_ONE64, FDT0, &env->fp_status); | ||
955 | + update_fcr31(); | ||
956 | +} | ||
957 | +FLOAT_OP(recip1, s) | ||
958 | +{ | ||
959 | + set_float_exception_flags(0, &env->fp_status); | ||
960 | + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); | ||
961 | + update_fcr31(); | ||
962 | +} | ||
963 | +FLOAT_OP(recip1, ps) | ||
964 | +{ | ||
965 | + set_float_exception_flags(0, &env->fp_status); | ||
966 | + FST2 = float32_div(FLOAT_ONE32, FST0, &env->fp_status); | ||
967 | + FSTH2 = float32_div(FLOAT_ONE32, FSTH0, &env->fp_status); | ||
968 | + update_fcr31(); | ||
969 | +} | ||
970 | + | ||
971 | +FLOAT_OP(rsqrt1, d) | ||
972 | +{ | ||
973 | + set_float_exception_flags(0, &env->fp_status); | ||
974 | + FDT2 = float64_sqrt(FDT0, &env->fp_status); | ||
975 | + FDT2 = float64_div(FLOAT_ONE64, FDT2, &env->fp_status); | ||
976 | + update_fcr31(); | ||
977 | +} | ||
978 | +FLOAT_OP(rsqrt1, s) | ||
979 | +{ | ||
980 | + set_float_exception_flags(0, &env->fp_status); | ||
981 | + FST2 = float32_sqrt(FST0, &env->fp_status); | ||
982 | + FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status); | ||
983 | + update_fcr31(); | ||
984 | +} | ||
985 | +FLOAT_OP(rsqrt1, ps) | ||
986 | +{ | ||
987 | + set_float_exception_flags(0, &env->fp_status); | ||
988 | + FST2 = float32_sqrt(FST0, &env->fp_status); | ||
989 | + FSTH2 = float32_sqrt(FSTH0, &env->fp_status); | ||
990 | + FST2 = float32_div(FLOAT_ONE32, FST2, &env->fp_status); | ||
991 | + FSTH2 = float32_div(FLOAT_ONE32, FSTH2, &env->fp_status); | ||
992 | + update_fcr31(); | ||
963 | } | 993 | } |
964 | -FLOAT_UNOP(rsqrt1) | ||
965 | -FLOAT_UNOP(recip1) | ||
966 | -#undef FLOAT_UNOP | ||
967 | 994 | ||
968 | /* binary operations */ | 995 | /* binary operations */ |
969 | #define FLOAT_BINOP(name) \ | 996 | #define FLOAT_BINOP(name) \ |
@@ -976,7 +1003,7 @@ FLOAT_OP(name, d) \ | @@ -976,7 +1003,7 @@ FLOAT_OP(name, d) \ | ||
976 | FDT2 = 0x7ff7ffffffffffffULL; \ | 1003 | FDT2 = 0x7ff7ffffffffffffULL; \ |
977 | else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | 1004 | else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ |
978 | if ((env->fcr31 & 0x3) == 0) \ | 1005 | if ((env->fcr31 & 0x3) == 0) \ |
979 | - FDT2 &= 0x8000000000000000ULL; \ | 1006 | + FDT2 &= FLOAT_SIGN64; \ |
980 | } \ | 1007 | } \ |
981 | } \ | 1008 | } \ |
982 | FLOAT_OP(name, s) \ | 1009 | FLOAT_OP(name, s) \ |
@@ -988,7 +1015,7 @@ FLOAT_OP(name, s) \ | @@ -988,7 +1015,7 @@ FLOAT_OP(name, s) \ | ||
988 | FST2 = 0x7fbfffff; \ | 1015 | FST2 = 0x7fbfffff; \ |
989 | else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | 1016 | else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ |
990 | if ((env->fcr31 & 0x3) == 0) \ | 1017 | if ((env->fcr31 & 0x3) == 0) \ |
991 | - FST2 &= 0x80000000ULL; \ | 1018 | + FST2 &= FLOAT_SIGN32; \ |
992 | } \ | 1019 | } \ |
993 | } \ | 1020 | } \ |
994 | FLOAT_OP(name, ps) \ | 1021 | FLOAT_OP(name, ps) \ |
@@ -1002,8 +1029,8 @@ FLOAT_OP(name, ps) \ | @@ -1002,8 +1029,8 @@ FLOAT_OP(name, ps) \ | ||
1002 | FSTH2 = 0x7fbfffff; \ | 1029 | FSTH2 = 0x7fbfffff; \ |
1003 | } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | 1030 | } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ |
1004 | if ((env->fcr31 & 0x3) == 0) { \ | 1031 | if ((env->fcr31 & 0x3) == 0) { \ |
1005 | - FST2 &= 0x80000000ULL; \ | ||
1006 | - FSTH2 &= 0x80000000ULL; \ | 1032 | + FST2 &= FLOAT_SIGN32; \ |
1033 | + FSTH2 &= FLOAT_SIGN32; \ | ||
1007 | } \ | 1034 | } \ |
1008 | } \ | 1035 | } \ |
1009 | } | 1036 | } |
@@ -1013,36 +1040,58 @@ FLOAT_BINOP(mul) | @@ -1013,36 +1040,58 @@ FLOAT_BINOP(mul) | ||
1013 | FLOAT_BINOP(div) | 1040 | FLOAT_BINOP(div) |
1014 | #undef FLOAT_BINOP | 1041 | #undef FLOAT_BINOP |
1015 | 1042 | ||
1016 | -/* binary operations, MIPS specific */ | ||
1017 | -#define FLOAT_BINOP(name) \ | ||
1018 | -FLOAT_OP(name, d) \ | ||
1019 | -{ \ | ||
1020 | - set_float_exception_flags(0, &env->fp_status); \ | ||
1021 | -/* XXX: not implemented */ \ | ||
1022 | -/* FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status);*/ \ | ||
1023 | -do_raise_exception(EXCP_RI); \ | ||
1024 | - update_fcr31(); \ | ||
1025 | -} \ | ||
1026 | -FLOAT_OP(name, s) \ | ||
1027 | -{ \ | ||
1028 | - set_float_exception_flags(0, &env->fp_status); \ | ||
1029 | -/* XXX: not implemented */ \ | ||
1030 | -/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \ | ||
1031 | -do_raise_exception(EXCP_RI); \ | ||
1032 | - update_fcr31(); \ | ||
1033 | -} \ | ||
1034 | -FLOAT_OP(name, ps) \ | ||
1035 | -{ \ | ||
1036 | - set_float_exception_flags(0, &env->fp_status); \ | ||
1037 | -/* XXX: not implemented */ \ | ||
1038 | -/* FST2 = float32_ ## name (FST0, FST1, &env->fp_status);*/ \ | ||
1039 | -/* FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status);*/ \ | ||
1040 | -do_raise_exception(EXCP_RI); \ | ||
1041 | - update_fcr31(); \ | 1043 | +/* MIPS specific binary operations */ |
1044 | +FLOAT_OP(recip2, d) | ||
1045 | +{ | ||
1046 | + set_float_exception_flags(0, &env->fp_status); | ||
1047 | + FDT2 = float64_mul(FDT0, FDT2, &env->fp_status); | ||
1048 | + FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status) ^ FLOAT_SIGN64; | ||
1049 | + update_fcr31(); | ||
1050 | +} | ||
1051 | +FLOAT_OP(recip2, s) | ||
1052 | +{ | ||
1053 | + set_float_exception_flags(0, &env->fp_status); | ||
1054 | + FST2 = float32_mul(FST0, FST2, &env->fp_status); | ||
1055 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; | ||
1056 | + update_fcr31(); | ||
1057 | +} | ||
1058 | +FLOAT_OP(recip2, ps) | ||
1059 | +{ | ||
1060 | + set_float_exception_flags(0, &env->fp_status); | ||
1061 | + FST2 = float32_mul(FST0, FST2, &env->fp_status); | ||
1062 | + FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status); | ||
1063 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; | ||
1064 | + FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status) ^ FLOAT_SIGN32; | ||
1065 | + update_fcr31(); | ||
1066 | +} | ||
1067 | + | ||
1068 | +FLOAT_OP(rsqrt2, d) | ||
1069 | +{ | ||
1070 | + set_float_exception_flags(0, &env->fp_status); | ||
1071 | + FDT2 = float64_mul(FDT0, FDT2, &env->fp_status); | ||
1072 | + FDT2 = float64_sub(FDT2, FLOAT_ONE64, &env->fp_status); | ||
1073 | + FDT2 = float64_div(FDT2, FLOAT_TWO64, &env->fp_status) ^ FLOAT_SIGN64; | ||
1074 | + update_fcr31(); | ||
1075 | +} | ||
1076 | +FLOAT_OP(rsqrt2, s) | ||
1077 | +{ | ||
1078 | + set_float_exception_flags(0, &env->fp_status); | ||
1079 | + FST2 = float32_mul(FST0, FST2, &env->fp_status); | ||
1080 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status); | ||
1081 | + FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32; | ||
1082 | + update_fcr31(); | ||
1083 | +} | ||
1084 | +FLOAT_OP(rsqrt2, ps) | ||
1085 | +{ | ||
1086 | + set_float_exception_flags(0, &env->fp_status); | ||
1087 | + FST2 = float32_mul(FST0, FST2, &env->fp_status); | ||
1088 | + FSTH2 = float32_mul(FSTH0, FSTH2, &env->fp_status); | ||
1089 | + FST2 = float32_sub(FST2, FLOAT_ONE32, &env->fp_status); | ||
1090 | + FSTH2 = float32_sub(FSTH2, FLOAT_ONE32, &env->fp_status); | ||
1091 | + FST2 = float32_div(FST2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32; | ||
1092 | + FSTH2 = float32_div(FSTH2, FLOAT_TWO32, &env->fp_status) ^ FLOAT_SIGN32; | ||
1093 | + update_fcr31(); | ||
1042 | } | 1094 | } |
1043 | -FLOAT_BINOP(rsqrt2) | ||
1044 | -FLOAT_BINOP(recip2) | ||
1045 | -#undef FLOAT_BINOP | ||
1046 | 1095 | ||
1047 | FLOAT_OP(addr, ps) | 1096 | FLOAT_OP(addr, ps) |
1048 | { | 1097 | { |
@@ -1060,6 +1109,7 @@ FLOAT_OP(mulr, ps) | @@ -1060,6 +1109,7 @@ FLOAT_OP(mulr, ps) | ||
1060 | update_fcr31(); | 1109 | update_fcr31(); |
1061 | } | 1110 | } |
1062 | 1111 | ||
1112 | +/* compare operations */ | ||
1063 | #define FOP_COND_D(op, cond) \ | 1113 | #define FOP_COND_D(op, cond) \ |
1064 | void do_cmp_d_ ## op (long cc) \ | 1114 | void do_cmp_d_ ## op (long cc) \ |
1065 | { \ | 1115 | { \ |
@@ -1073,8 +1123,8 @@ void do_cmp_d_ ## op (long cc) \ | @@ -1073,8 +1123,8 @@ void do_cmp_d_ ## op (long cc) \ | ||
1073 | void do_cmpabs_d_ ## op (long cc) \ | 1123 | void do_cmpabs_d_ ## op (long cc) \ |
1074 | { \ | 1124 | { \ |
1075 | int c; \ | 1125 | int c; \ |
1076 | - FDT0 &= ~(1ULL << 63); \ | ||
1077 | - FDT1 &= ~(1ULL << 63); \ | 1126 | + FDT0 &= ~FLOAT_SIGN64; \ |
1127 | + FDT1 &= ~FLOAT_SIGN64; \ | ||
1078 | c = cond; \ | 1128 | c = cond; \ |
1079 | update_fcr31(); \ | 1129 | update_fcr31(); \ |
1080 | if (c) \ | 1130 | if (c) \ |
@@ -1131,8 +1181,8 @@ void do_cmp_s_ ## op (long cc) \ | @@ -1131,8 +1181,8 @@ void do_cmp_s_ ## op (long cc) \ | ||
1131 | void do_cmpabs_s_ ## op (long cc) \ | 1181 | void do_cmpabs_s_ ## op (long cc) \ |
1132 | { \ | 1182 | { \ |
1133 | int c; \ | 1183 | int c; \ |
1134 | - FST0 &= ~(1 << 31); \ | ||
1135 | - FST1 &= ~(1 << 31); \ | 1184 | + FST0 &= ~FLOAT_SIGN32; \ |
1185 | + FST1 &= ~FLOAT_SIGN32; \ | ||
1136 | c = cond; \ | 1186 | c = cond; \ |
1137 | update_fcr31(); \ | 1187 | update_fcr31(); \ |
1138 | if (c) \ | 1188 | if (c) \ |
@@ -1194,10 +1244,10 @@ void do_cmp_ps_ ## op (long cc) \ | @@ -1194,10 +1244,10 @@ void do_cmp_ps_ ## op (long cc) \ | ||
1194 | void do_cmpabs_ps_ ## op (long cc) \ | 1244 | void do_cmpabs_ps_ ## op (long cc) \ |
1195 | { \ | 1245 | { \ |
1196 | int cl, ch; \ | 1246 | int cl, ch; \ |
1197 | - FST0 &= ~(1 << 31); \ | ||
1198 | - FSTH0 &= ~(1 << 31); \ | ||
1199 | - FST1 &= ~(1 << 31); \ | ||
1200 | - FSTH1 &= ~(1 << 31); \ | 1247 | + FST0 &= ~FLOAT_SIGN32; \ |
1248 | + FSTH0 &= ~FLOAT_SIGN32; \ | ||
1249 | + FST1 &= ~FLOAT_SIGN32; \ | ||
1250 | + FSTH1 &= ~FLOAT_SIGN32; \ | ||
1201 | cl = condl; \ | 1251 | cl = condl; \ |
1202 | ch = condh; \ | 1252 | ch = condh; \ |
1203 | update_fcr31(); \ | 1253 | update_fcr31(); \ |
target-mips/translate.c
@@ -4551,7 +4551,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, | @@ -4551,7 +4551,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, | ||
4551 | case FOP(31, 16): | 4551 | case FOP(31, 16): |
4552 | check_cp1_64bitmode(ctx); | 4552 | check_cp1_64bitmode(ctx); |
4553 | GEN_LOAD_FREG_FTN(WT0, fs); | 4553 | GEN_LOAD_FREG_FTN(WT0, fs); |
4554 | - GEN_LOAD_FREG_FTN(WT2, fd); | 4554 | + GEN_LOAD_FREG_FTN(WT2, ft); |
4555 | gen_op_float_rsqrt2_s(); | 4555 | gen_op_float_rsqrt2_s(); |
4556 | GEN_STORE_FTN_FREG(fd, WT2); | 4556 | GEN_STORE_FTN_FREG(fd, WT2); |
4557 | opn = "rsqrt2.s"; | 4557 | opn = "rsqrt2.s"; |
@@ -5036,8 +5036,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, | @@ -5036,8 +5036,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, | ||
5036 | check_cp1_64bitmode(ctx); | 5036 | check_cp1_64bitmode(ctx); |
5037 | GEN_LOAD_FREG_FTN(WT0, fs); | 5037 | GEN_LOAD_FREG_FTN(WT0, fs); |
5038 | GEN_LOAD_FREG_FTN(WTH0, fs); | 5038 | GEN_LOAD_FREG_FTN(WTH0, fs); |
5039 | - GEN_LOAD_FREG_FTN(WT2, fd); | ||
5040 | - GEN_LOAD_FREG_FTN(WTH2, fd); | 5039 | + GEN_LOAD_FREG_FTN(WT2, ft); |
5040 | + GEN_LOAD_FREG_FTN(WTH2, ft); | ||
5041 | gen_op_float_rsqrt2_ps(); | 5041 | gen_op_float_rsqrt2_ps(); |
5042 | GEN_STORE_FTN_FREG(fd, WT2); | 5042 | GEN_STORE_FTN_FREG(fd, WT2); |
5043 | GEN_STORE_FTN_FREG(fd, WTH2); | 5043 | GEN_STORE_FTN_FREG(fd, WTH2); |