Patchwork [2/2] SPARC64: implement %fprs dirty bits

login
register
mail settings
Submitter Tsuneo Saito
Date July 23, 2011, 2:20 a.m.
Message ID <1311387607-56720-3-git-send-email-tsnsaito@gmail.com>
Download mbox | patch
Permalink /patch/106408/
State New
Headers show

Comments

Tsuneo Saito - July 23, 2011, 2:20 a.m.
Implement %fprs.DU/DL bits.
The FPU sets %fprs.DL and %fprs.DU when values are assigned to %f0-31
and %f32-63 respectively.

Signed-off-by: Tsuneo Saito <tsnsaito@gmail.com>
---
 target-sparc/translate.c |  116 ++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 116 insertions(+), 0 deletions(-)

Patch

diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index f68b3bc..958fbc5 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1558,6 +1558,13 @@  static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond)
     return 0;
 }
 
+static inline void gen_update_fprs_dirty(int rd)
+{
+#if defined(TARGET_SPARC64)
+    tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2);
+#endif
+}
+
 static inline void gen_op_clear_ieee_excp_and_FTT(void)
 {
     tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK);
@@ -2351,12 +2358,15 @@  static void disas_sparc_insn(DisasContext * dc)
                 switch (xop) {
                 case 0x1: /* fmovs */
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x5: /* fnegs */
                     gen_helper_fnegs(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x9: /* fabss */
                     gen_helper_fabss(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x29: /* fsqrts */
                     CHECK_FPU_FEATURE(dc, FSQRT);
@@ -2364,6 +2374,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x2a: /* fsqrtd */
                     CHECK_FPU_FEATURE(dc, FSQRT);
@@ -2372,6 +2383,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrtd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x2b: /* fsqrtq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2380,12 +2392,14 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsqrtq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x41: /* fadds */
                     gen_clear_float_exceptions();
                     gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x42: /* faddd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2394,6 +2408,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_faddd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x43: /* faddq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2403,12 +2418,14 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_faddq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x45: /* fsubs */
                     gen_clear_float_exceptions();
                     gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x46: /* fsubd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2417,6 +2434,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsubd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x47: /* fsubq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2426,6 +2444,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsubq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x49: /* fmuls */
                     CHECK_FPU_FEATURE(dc, FMUL);
@@ -2433,6 +2452,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x4a: /* fmuld */
                     CHECK_FPU_FEATURE(dc, FMUL);
@@ -2442,6 +2462,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmuld();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x4b: /* fmulq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2452,12 +2473,14 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fmulq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x4d: /* fdivs */
                     gen_clear_float_exceptions();
                     gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x4e: /* fdivd */
                     gen_op_load_fpr_DT0(DFPREG(rs1));
@@ -2466,6 +2489,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdivd();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x4f: /* fdivq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2475,6 +2499,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdivq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x69: /* fsmuld */
                     CHECK_FPU_FEATURE(dc, FSMULD);
@@ -2482,6 +2507,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x6e: /* fdmulq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2491,12 +2517,14 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdmulq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xc4: /* fitos */
                     gen_clear_float_exceptions();
                     gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc6: /* fdtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2504,6 +2532,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc7: /* fqtos */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2512,14 +2541,17 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xc8: /* fitod */
                     gen_helper_fitod(cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xc9: /* fstod */
                     gen_helper_fstod(cpu_fpr[rs2]);
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcb: /* fqtod */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2528,28 +2560,33 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtod();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xcc: /* fitoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_helper_fitoq(cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xcd: /* fstoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_helper_fstoq(cpu_fpr[rs2]);
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xce: /* fdtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fdtoq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xd1: /* fstoi */
                     gen_clear_float_exceptions();
                     gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xd2: /* fdtoi */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2557,6 +2594,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtoi(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0xd3: /* fqtoi */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2565,12 +2603,14 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtoi(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
 #ifdef TARGET_SPARC64
                 case 0x2: /* V9 fmovd */
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x3: /* V9 fmovq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2581,34 +2621,40 @@  static void disas_sparc_insn(DisasContext * dc)
                                     cpu_fpr[QFPREG(rs2) + 2]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],
                                     cpu_fpr[QFPREG(rs2) + 3]);
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x6: /* V9 fnegd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fnegd();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x7: /* V9 fnegq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_helper_fnegq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0xa: /* V9 fabsd */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fabsd();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0xb: /* V9 fabsq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
                     gen_op_load_fpr_QT1(QFPREG(rs2));
                     gen_helper_fabsq();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
                 case 0x81: /* V9 fstox */
                     gen_clear_float_exceptions();
                     gen_helper_fstox(cpu_fpr[rs2]);
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x82: /* V9 fdtox */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2616,6 +2662,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fdtox();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x83: /* V9 fqtox */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2624,6 +2671,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fqtox();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x84: /* V9 fxtos */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2631,6 +2679,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtos(cpu_tmp32);
                     gen_helper_check_ieee_exceptions();
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x88: /* V9 fxtod */
                     gen_op_load_fpr_DT1(DFPREG(rs2));
@@ -2638,6 +2687,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtod();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x8c: /* V9 fxtoq */
                     CHECK_FPU_FEATURE(dc, FLOAT128);
@@ -2646,6 +2696,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_helper_fxtoq();
                     gen_helper_check_ieee_exceptions();
                     gen_op_store_QT0_fpr(QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     break;
 #endif
                 default:
@@ -2672,6 +2723,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1,
                                        0, l1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     gen_set_label(l1);
                     break;
                 } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr
@@ -2684,6 +2736,7 @@  static void disas_sparc_insn(DisasContext * dc)
                                        0, l1);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     gen_set_label(l1);
                     break;
                 } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr
@@ -2699,6 +2752,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1], cpu_fpr[QFPREG(rs2) + 1]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2], cpu_fpr[QFPREG(rs2) + 2]);
                     tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], cpu_fpr[QFPREG(rs2) + 3]);
+                    gen_update_fprs_dirty(QFPREG(rd));
                     gen_set_label(l1);
                     break;
                 }
@@ -2717,6 +2771,7 @@  static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                            0, l1);                      \
                         tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
+                        gen_update_fprs_dirty(rd);                      \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2735,6 +2790,7 @@  static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[DFPREG(rs2)]);          \
                         tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                         cpu_fpr[DFPREG(rs2) + 1]);      \
+                        gen_update_fprs_dirty(DFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2757,6 +2813,7 @@  static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[QFPREG(rs2) + 2]);      \
                         tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                         cpu_fpr[QFPREG(rs2) + 3]);      \
+                        gen_update_fprs_dirty(QFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2815,6 +2872,7 @@  static void disas_sparc_insn(DisasContext * dc)
                         tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond,         \
                                            0, l1);                      \
                         tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);     \
+                        gen_update_fprs_dirty(rd);                      \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2833,6 +2891,7 @@  static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[DFPREG(rs2)]);          \
                         tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],        \
                                         cpu_fpr[DFPREG(rs2) + 1]);      \
+                        gen_update_fprs_dirty(DFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -2855,6 +2914,7 @@  static void disas_sparc_insn(DisasContext * dc)
                                         cpu_fpr[QFPREG(rs2) + 2]);      \
                         tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3],        \
                                         cpu_fpr[QFPREG(rs2) + 3]);      \
+                        gen_update_fprs_dirty(QFPREG(rd));              \
                         gen_set_label(l1);                              \
                         tcg_temp_free(r_cond);                          \
                     }
@@ -3848,6 +3908,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x033: /* VIS I fmul8x16au */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3855,6 +3916,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16au();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x035: /* VIS I fmul8x16al */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3862,6 +3924,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8x16al();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x036: /* VIS I fmul8sux16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3869,6 +3932,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8sux16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x037: /* VIS I fmul8ulx16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3876,6 +3940,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmul8ulx16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x038: /* VIS I fmuld8sux16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3883,6 +3948,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmuld8sux16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x039: /* VIS I fmuld8ulx16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3890,6 +3956,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fmuld8ulx16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x03a: /* VIS I fpack32 */
                 case 0x03b: /* VIS I fpack16 */
@@ -3903,6 +3970,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_faligndata();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x04b: /* VIS I fpmerge */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3910,6 +3978,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpmerge();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x04c: /* VIS II bshuffle */
                     // XXX
@@ -3920,6 +3989,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fexpand();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x050: /* VIS I fpadd16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3927,11 +3997,13 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpadd16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x051: /* VIS I fpadd16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpadd16s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x052: /* VIS I fpadd32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3939,11 +4011,13 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpadd32();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x053: /* VIS I fpadd32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpadd32s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x054: /* VIS I fpsub16 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3951,11 +4025,13 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpsub16();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x055: /* VIS I fpsub16s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpsub16s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x056: /* VIS I fpsub32 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3963,20 +4039,24 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_op_load_fpr_DT1(DFPREG(rs2));
                     gen_helper_fpsub32();
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x057: /* VIS I fpsub32s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_helper_fpsub32s(cpu_fpr[rd],
                                         cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x060: /* VIS I fzero */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], 0);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], 0);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x061: /* VIS I fzeros */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[rd], 0);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x062: /* VIS I fnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3985,10 +4065,12 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_nor_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x063: /* VIS I fnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_nor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x064: /* VIS I fandnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -3997,20 +4079,24 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x065: /* VIS I fandnot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x066: /* VIS I fnot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x067: /* VIS I fnot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x068: /* VIS I fandnot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4019,20 +4105,24 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x069: /* VIS I fandnot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06a: /* VIS I fnot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                     tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06b: /* VIS I fnot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06c: /* VIS I fxor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4041,10 +4131,12 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06d: /* VIS I fxors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_xor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x06e: /* VIS I fnand */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4053,10 +4145,12 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_nand_i32(cpu_fpr[DFPREG(rd) + 1],
                                      cpu_fpr[DFPREG(rs1) + 1],
                                      cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x06f: /* VIS I fnands */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_nand_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x070: /* VIS I fand */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4065,10 +4159,12 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_and_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x071: /* VIS I fands */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_and_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x072: /* VIS I fxnor */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4078,21 +4174,25 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[DFPREG(rs2) + 1], -1);
                     tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1], cpu_tmp32,
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x073: /* VIS I fxnors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[rs2], -1);
                     tcg_gen_xor_i32(cpu_fpr[rd], cpu_tmp32, cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x074: /* VIS I fsrc1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]);
                     tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x075: /* VIS I fsrc1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x076: /* VIS I fornot2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4101,19 +4201,23 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x077: /* VIS I fornot2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x078: /* VIS I fsrc2 */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     gen_op_load_fpr_DT0(DFPREG(rs2));
                     gen_op_store_DT0_fpr(DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x079: /* VIS I fsrc2s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07a: /* VIS I fornot1 */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4122,10 +4226,12 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1],
                                     cpu_fpr[DFPREG(rs2) + 1],
                                     cpu_fpr[DFPREG(rs1) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07b: /* VIS I fornot1s */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07c: /* VIS I for */
                     CHECK_FPU_FEATURE(dc, VIS1);
@@ -4134,19 +4240,23 @@  static void disas_sparc_insn(DisasContext * dc)
                     tcg_gen_or_i32(cpu_fpr[DFPREG(rd) + 1],
                                    cpu_fpr[DFPREG(rs1) + 1],
                                    cpu_fpr[DFPREG(rs2) + 1]);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07d: /* VIS I fors */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_or_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x07e: /* VIS I fone */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], -1);
                     tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], -1);
+                    gen_update_fprs_dirty(DFPREG(rd));
                     break;
                 case 0x07f: /* VIS I fones */
                     CHECK_FPU_FEATURE(dc, VIS1);
                     tcg_gen_movi_i32(cpu_fpr[rd], -1);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x080: /* VIS I shutdown */
                 case 0x081: /* VIS II siam */
@@ -4492,6 +4602,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 4, rd);
+                    gen_update_fprs_dirty(rd);
                     goto skip_move;
                 case 0x33: /* V9 lddfa */
                     if (gen_trap_ifnofpu(dc, cpu_cond)) {
@@ -4499,6 +4610,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd));
+                    gen_update_fprs_dirty(DFPREG(rd));
                     goto skip_move;
                 case 0x3d: /* V9 prefetcha, no effect */
                     goto skip_move;
@@ -4509,6 +4621,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     }
                     save_state(dc, cpu_cond);
                     gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd));
+                    gen_update_fprs_dirty(QFPREG(rd));
                     goto skip_move;
 #endif
                 default:
@@ -4527,6 +4640,7 @@  static void disas_sparc_insn(DisasContext * dc)
                     gen_address_mask(dc, cpu_addr);
                     tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
                     tcg_gen_trunc_tl_i32(cpu_fpr[rd], cpu_tmp0);
+                    gen_update_fprs_dirty(rd);
                     break;
                 case 0x21:      /* ldfsr, V9 ldxfsr */
 #ifdef TARGET_SPARC64
@@ -4556,6 +4670,7 @@  static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_ldqf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_QT0_fpr(QFPREG(rd));
+                        gen_update_fprs_dirty(QFPREG(rd));
                     }
                     break;
                 case 0x23:      /* lddf, load double fpreg */
@@ -4567,6 +4682,7 @@  static void disas_sparc_insn(DisasContext * dc)
                         gen_helper_lddf(cpu_addr, r_const);
                         tcg_temp_free_i32(r_const);
                         gen_op_store_DT0_fpr(DFPREG(rd));
+                        gen_update_fprs_dirty(DFPREG(rd));
                     }
                     break;
                 default: