Commit 8dfdb87c8d675b846e12c8066922525e22bcfc50

Authored by ths
1 parent d79acba4

Implement recip1/recip2/rsqrt1/rsqrt2.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3026 c046a42c-6fe2-441c-8c8c-71466251a162
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);