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 | 597 | |
598 | 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 | 607 | /* convert MIPS rounding mode in FCR31 to IEEE library */ |
601 | 608 | unsigned int ieee_rm[] = { |
602 | 609 | float_round_nearest_even, |
... | ... | @@ -912,58 +919,78 @@ FLOAT_OP(floorw, s) |
912 | 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 | 995 | /* binary operations */ |
969 | 996 | #define FLOAT_BINOP(name) \ |
... | ... | @@ -976,7 +1003,7 @@ FLOAT_OP(name, d) \ |
976 | 1003 | FDT2 = 0x7ff7ffffffffffffULL; \ |
977 | 1004 | else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ |
978 | 1005 | if ((env->fcr31 & 0x3) == 0) \ |
979 | - FDT2 &= 0x8000000000000000ULL; \ | |
1006 | + FDT2 &= FLOAT_SIGN64; \ | |
980 | 1007 | } \ |
981 | 1008 | } \ |
982 | 1009 | FLOAT_OP(name, s) \ |
... | ... | @@ -988,7 +1015,7 @@ FLOAT_OP(name, s) \ |
988 | 1015 | FST2 = 0x7fbfffff; \ |
989 | 1016 | else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ |
990 | 1017 | if ((env->fcr31 & 0x3) == 0) \ |
991 | - FST2 &= 0x80000000ULL; \ | |
1018 | + FST2 &= FLOAT_SIGN32; \ | |
992 | 1019 | } \ |
993 | 1020 | } \ |
994 | 1021 | FLOAT_OP(name, ps) \ |
... | ... | @@ -1002,8 +1029,8 @@ FLOAT_OP(name, ps) \ |
1002 | 1029 | FSTH2 = 0x7fbfffff; \ |
1003 | 1030 | } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ |
1004 | 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 | 1040 | FLOAT_BINOP(div) |
1014 | 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 | 1096 | FLOAT_OP(addr, ps) |
1048 | 1097 | { |
... | ... | @@ -1060,6 +1109,7 @@ FLOAT_OP(mulr, ps) |
1060 | 1109 | update_fcr31(); |
1061 | 1110 | } |
1062 | 1111 | |
1112 | +/* compare operations */ | |
1063 | 1113 | #define FOP_COND_D(op, cond) \ |
1064 | 1114 | void do_cmp_d_ ## op (long cc) \ |
1065 | 1115 | { \ |
... | ... | @@ -1073,8 +1123,8 @@ void do_cmp_d_ ## op (long cc) \ |
1073 | 1123 | void do_cmpabs_d_ ## op (long cc) \ |
1074 | 1124 | { \ |
1075 | 1125 | int c; \ |
1076 | - FDT0 &= ~(1ULL << 63); \ | |
1077 | - FDT1 &= ~(1ULL << 63); \ | |
1126 | + FDT0 &= ~FLOAT_SIGN64; \ | |
1127 | + FDT1 &= ~FLOAT_SIGN64; \ | |
1078 | 1128 | c = cond; \ |
1079 | 1129 | update_fcr31(); \ |
1080 | 1130 | if (c) \ |
... | ... | @@ -1131,8 +1181,8 @@ void do_cmp_s_ ## op (long cc) \ |
1131 | 1181 | void do_cmpabs_s_ ## op (long cc) \ |
1132 | 1182 | { \ |
1133 | 1183 | int c; \ |
1134 | - FST0 &= ~(1 << 31); \ | |
1135 | - FST1 &= ~(1 << 31); \ | |
1184 | + FST0 &= ~FLOAT_SIGN32; \ | |
1185 | + FST1 &= ~FLOAT_SIGN32; \ | |
1136 | 1186 | c = cond; \ |
1137 | 1187 | update_fcr31(); \ |
1138 | 1188 | if (c) \ |
... | ... | @@ -1194,10 +1244,10 @@ void do_cmp_ps_ ## op (long cc) \ |
1194 | 1244 | void do_cmpabs_ps_ ## op (long cc) \ |
1195 | 1245 | { \ |
1196 | 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 | 1251 | cl = condl; \ |
1202 | 1252 | ch = condh; \ |
1203 | 1253 | update_fcr31(); \ | ... | ... |
target-mips/translate.c
... | ... | @@ -4551,7 +4551,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, |
4551 | 4551 | case FOP(31, 16): |
4552 | 4552 | check_cp1_64bitmode(ctx); |
4553 | 4553 | GEN_LOAD_FREG_FTN(WT0, fs); |
4554 | - GEN_LOAD_FREG_FTN(WT2, fd); | |
4554 | + GEN_LOAD_FREG_FTN(WT2, ft); | |
4555 | 4555 | gen_op_float_rsqrt2_s(); |
4556 | 4556 | GEN_STORE_FTN_FREG(fd, WT2); |
4557 | 4557 | opn = "rsqrt2.s"; |
... | ... | @@ -5036,8 +5036,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, |
5036 | 5036 | check_cp1_64bitmode(ctx); |
5037 | 5037 | GEN_LOAD_FREG_FTN(WT0, fs); |
5038 | 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 | 5041 | gen_op_float_rsqrt2_ps(); |
5042 | 5042 | GEN_STORE_FTN_FREG(fd, WT2); |
5043 | 5043 | GEN_STORE_FTN_FREG(fd, WTH2); | ... | ... |