target-ppc: fix mtfsb0 and mtfsb1 Signed-off-by: Aurelien Jarno <aurelien@aurel32.net> git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6032 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 26d1627..dc47040 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h
@@ -58,6 +58,7 @@ #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 cd88bb6..a46c00c 100644 --- a/target-ppc/op_helper.c +++ b/target-ppc/op_helper.c
@@ -843,6 +843,24 @@ 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 57ea907..11a8334 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c
@@ -2355,11 +2355,14 @@ 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_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 */