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