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 | 975 | { \ |
976 | 976 | set_float_exception_flags(0, &env->fp_status); \ |
977 | 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 | 986 | FLOAT_OP(name, s) \ |
981 | 987 | { \ |
982 | 988 | set_float_exception_flags(0, &env->fp_status); \ |
983 | 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 | 998 | FLOAT_OP(name, ps) \ |
987 | 999 | { \ |
... | ... | @@ -989,6 +1001,15 @@ FLOAT_OP(name, ps) \ |
989 | 1001 | FST2 = float32_ ## name (FST0, FST1, &env->fp_status); \ |
990 | 1002 | FSTH2 = float32_ ## name (FSTH0, FSTH1, &env->fp_status); \ |
991 | 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 | 1014 | FLOAT_BINOP(add) |
994 | 1015 | FLOAT_BINOP(sub) | ... | ... |
target-mips/translate.c
... | ... | @@ -5074,10 +5074,10 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
5074 | 5074 | break; |
5075 | 5075 | case FOP(24, 22): |
5076 | 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 | 5081 | gen_op_float_addr_ps(); |
5082 | 5082 | GEN_STORE_FTN_FREG(fd, WT2); |
5083 | 5083 | GEN_STORE_FTN_FREG(fd, WTH2); |
... | ... | @@ -5085,10 +5085,10 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, int ft, |
5085 | 5085 | break; |
5086 | 5086 | case FOP(26, 22): |
5087 | 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 | 5092 | gen_op_float_mulr_ps(); |
5093 | 5093 | GEN_STORE_FTN_FREG(fd, WT2); |
5094 | 5094 | GEN_STORE_FTN_FREG(fd, WTH2); | ... | ... |