diff options
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 0219d38ace..7db3145cff 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -2501,18 +2501,31 @@ static void gen_fmrgow(DisasContext *ctx) static void gen_mcrfs(DisasContext *ctx) { TCGv tmp = tcg_temp_new(); + TCGv_i32 tmask; + TCGv_i64 tnew_fpscr = tcg_temp_new_i64(); int bfa; + int nibble; + int shift; if (unlikely(!ctx->fpu_enabled)) { gen_exception(ctx, POWERPC_EXCP_FPU); return; } - bfa = 4 * (7 - crfS(ctx->opcode)); - tcg_gen_shri_tl(tmp, cpu_fpscr, bfa); + bfa = crfS(ctx->opcode); + nibble = 7 - bfa; + shift = 4 * nibble; + tcg_gen_shri_tl(tmp, cpu_fpscr, shift); tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp); - tcg_temp_free(tmp); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf); - tcg_gen_andi_tl(cpu_fpscr, cpu_fpscr, ~(0xF << bfa)); + tcg_temp_free(tmp); + tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr); + /* Only the exception bits (including FX) should be cleared if read */ + tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr, ~((0xF << shift) & FP_EX_CLEAR_BITS)); + /* FEX and VX need to be updated, so don't set fpscr directly */ + tmask = tcg_const_i32(1 << nibble); + gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask); + tcg_temp_free_i32(tmask); + tcg_temp_free_i64(tnew_fpscr); } /* mffs */ |