diff options
-rw-r--r-- | target-ppc/helper.h | 1 | ||||
-rw-r--r-- | target-ppc/op_helper.c | 18 | ||||
-rw-r--r-- | target-ppc/translate.c | 11 |
3 files changed, 26 insertions, 4 deletions
diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 26d16276c2..dc47040dd8 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -58,6 +58,7 @@ DEF_HELPER_0(reset_fpstatus, void) #endif DEF_HELPER_2(compute_fprf, i32, i64, i32) DEF_HELPER_2(store_fpscr, void, i64, i32) +DEF_HELPER_1(fpscr_clrbit, void, i32) DEF_HELPER_1(fpscr_setbit, void, i32) DEF_HELPER_1(float64_to_float32, i32, i64) DEF_HELPER_1(float32_to_float64, i64, i32) diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c index cd88bb6075..a46c00c9d7 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c @@ -843,6 +843,24 @@ static always_inline void fpscr_set_rounding_mode (void) set_float_rounding_mode(rnd_type, &env->fp_status); } +void helper_fpscr_clrbit (uint32_t bit) +{ + int prev; + + prev = (env->fpscr >> bit) & 1; + env->fpscr &= ~(1 << bit); + if (prev == 1) { + switch (bit) { + case FPSCR_RN1: + case FPSCR_RN: + fpscr_set_rounding_mode(); + break; + default: + break; + } + } +} + void helper_fpscr_setbit (uint32_t bit) { int prev; diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 57ea907b72..11a83348a9 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -2355,11 +2355,14 @@ GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT) gen_exception(ctx, POWERPC_EXCP_FPU); return; } - crb = 32 - (crbD(ctx->opcode) >> 2); + crb = 31 - crbD(ctx->opcode); gen_optimize_fprf(); gen_reset_fpstatus(); - if (likely(crb != 30 && crb != 29)) - tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(1 << crb)); + if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) { + TCGv_i32 t0 = tcg_const_i32(crb); + gen_helper_fpscr_clrbit(t0); + tcg_temp_free_i32(t0); + } if (unlikely(Rc(ctx->opcode) != 0)) { tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX); } @@ -2374,7 +2377,7 @@ GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT) gen_exception(ctx, POWERPC_EXCP_FPU); return; } - crb = 32 - (crbD(ctx->opcode) >> 2); + crb = 31 - crbD(ctx->opcode); gen_optimize_fprf(); gen_reset_fpstatus(); /* XXX: we pretend we can only do IEEE floating-point computations */ |