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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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(); \
|