Commit 3a5b360dac4ce1900e1cb19b7ad870086936869c
1 parent
5f30d62c
Catch more MIPS FPU cornercases, fix addr.ps and mulr.ps instructions.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2841 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
31 additions
and
10 deletions
target-mips/op_helper.c
@@ -975,13 +975,25 @@ FLOAT_OP(name, d) \ | @@ -975,13 +975,25 @@ FLOAT_OP(name, d) \ | ||
975 | { \ | 975 | { \ |
976 | set_float_exception_flags(0, &env->fp_status); \ | 976 | set_float_exception_flags(0, &env->fp_status); \ |
977 | FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ | 977 | FDT2 = float64_ ## name (FDT0, FDT1, &env->fp_status); \ |
978 | - update_fcr31(); \ | 978 | + update_fcr31(); \ |
979 | + if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \ | ||
980 | + FDT2 = 0x7ff7ffffffffffffULL; \ | ||
981 | + else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | ||
982 | + if ((env->fcr31 & 0x3) == 0) \ | ||
983 | + FDT2 &= 0x8000000000000000ULL; \ | ||
984 | + } \ | ||
979 | } \ | 985 | } \ |
980 | FLOAT_OP(name, s) \ | 986 | FLOAT_OP(name, s) \ |
981 | { \ | 987 | { \ |
982 | set_float_exception_flags(0, &env->fp_status); \ | 988 | set_float_exception_flags(0, &env->fp_status); \ |
983 | FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ | 989 | FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
984 | - update_fcr31(); \ | 990 | + update_fcr31(); \ |
991 | + if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) \ | ||
992 | + FST2 = 0x7fbfffff; \ | ||
993 | + else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | ||
994 | + if ((env->fcr31 & 0x3) == 0) \ | ||
995 | + FST2 &= 0x80000000ULL; \ | ||
996 | + } \ | ||
985 | } \ | 997 | } \ |
986 | FLOAT_OP(name, ps) \ | 998 | FLOAT_OP(name, ps) \ |
987 | { \ | 999 | { \ |
@@ -989,6 +1001,15 @@ FLOAT_OP(name, ps) \ | @@ -989,6 +1001,15 @@ FLOAT_OP(name, ps) \ | ||
989 | FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ | 1001 | FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
990 | FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ | 1002 | FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ |
991 | update_fcr31(); \ | 1003 | update_fcr31(); \ |
1004 | + if (GET_FP_CAUSE(env->fcr31) & FP_INVALID) { \ | ||
1005 | + FST2 = 0x7fbfffff; \ | ||
1006 | + FSTH2 = 0x7fbfffff; \ | ||
1007 | + } else if (GET_FP_CAUSE(env->fcr31) & FP_UNDERFLOW) { \ | ||
1008 | + if ((env->fcr31 & 0x3) == 0) { \ | ||
1009 | + FST2 &= 0x80000000ULL; \ | ||
1010 | + FSTH2 &= 0x80000000ULL; \ | ||
1011 | + } \ | ||
1012 | + } \ | ||
992 | } | 1013 | } |
993 | FLOAT_BINOP(add) | 1014 | FLOAT_BINOP(add) |
994 | FLOAT_BINOP(sub) | 1015 | FLOAT_BINOP(sub) |
target-mips/translate.c
@@ -5074,10 +5074,10 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -5074,10 +5074,10 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
5074 | break; | 5074 | break; |
5075 | case FOP(24, 22): | 5075 | case FOP(24, 22): |
5076 | gen_op_cp1_64bitmode(); | 5076 | gen_op_cp1_64bitmode(); |
5077 | - GEN_LOAD_FREG_FTN(WT0, fs); | ||
5078 | - GEN_LOAD_FREG_FTN(WTH0, fs); | ||
5079 | - GEN_LOAD_FREG_FTN(WT1, ft); | ||
5080 | - GEN_LOAD_FREG_FTN(WTH1, ft); | 5077 | + GEN_LOAD_FREG_FTN(WT0, ft); |
5078 | + GEN_LOAD_FREG_FTN(WTH0, ft); | ||
5079 | + GEN_LOAD_FREG_FTN(WT1, fs); | ||
5080 | + GEN_LOAD_FREG_FTN(WTH1, fs); | ||
5081 | gen_op_float_addr_ps(); | 5081 | gen_op_float_addr_ps(); |
5082 | GEN_STORE_FTN_FREG(fd, WT2); | 5082 | GEN_STORE_FTN_FREG(fd, WT2); |
5083 | GEN_STORE_FTN_FREG(fd, WTH2); | 5083 | GEN_STORE_FTN_FREG(fd, WTH2); |
@@ -5085,10 +5085,10 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | @@ -5085,10 +5085,10 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, | ||
5085 | break; | 5085 | break; |
5086 | case FOP(26, 22): | 5086 | case FOP(26, 22): |
5087 | gen_op_cp1_64bitmode(); | 5087 | gen_op_cp1_64bitmode(); |
5088 | - GEN_LOAD_FREG_FTN(WT0, fs); | ||
5089 | - GEN_LOAD_FREG_FTN(WTH0, fs); | ||
5090 | - GEN_LOAD_FREG_FTN(WT1, ft); | ||
5091 | - GEN_LOAD_FREG_FTN(WTH1, ft); | 5088 | + GEN_LOAD_FREG_FTN(WT0, ft); |
5089 | + GEN_LOAD_FREG_FTN(WTH0, ft); | ||
5090 | + GEN_LOAD_FREG_FTN(WT1, fs); | ||
5091 | + GEN_LOAD_FREG_FTN(WTH1, fs); | ||
5092 | gen_op_float_mulr_ps(); | 5092 | gen_op_float_mulr_ps(); |
5093 | GEN_STORE_FTN_FREG(fd, WT2); | 5093 | GEN_STORE_FTN_FREG(fd, WT2); |
5094 | GEN_STORE_FTN_FREG(fd, WTH2); | 5094 | GEN_STORE_FTN_FREG(fd, WTH2); |