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 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);
... ...