diff options
Diffstat (limited to 'target-alpha')
-rw-r--r-- | target-alpha/helper.h | 3 | ||||
-rw-r--r-- | target-alpha/op_helper.c | 11 | ||||
-rw-r--r-- | target-alpha/translate.c | 32 |
3 files changed, 34 insertions, 12 deletions
diff --git a/target-alpha/helper.h b/target-alpha/helper.h index 9ffc372af..2dec57e44 100644 --- a/target-alpha/helper.h +++ b/target-alpha/helper.h @@ -110,6 +110,9 @@ DEF_HELPER_2(stl_phys, void, i64, i64) DEF_HELPER_2(stq_phys, void, i64, i64) DEF_HELPER_2(stl_c_phys, i64, i64, i64) DEF_HELPER_2(stq_c_phys, i64, i64, i64) + +DEF_HELPER_FLAGS_0(tbia, TCG_CALL_CONST, void) +DEF_HELPER_FLAGS_1(tbis, TCG_CALL_CONST, void, i64) #endif #include "def-helper.h" diff --git a/target-alpha/op_helper.c b/target-alpha/op_helper.c index 36b82899d..d33271958 100644 --- a/target-alpha/op_helper.c +++ b/target-alpha/op_helper.c @@ -1205,6 +1205,16 @@ void helper_hw_ret (uint64_t a) swap_shadow_regs(env); } } + +void helper_tbia(void) +{ + tlb_flush(env, 1); +} + +void helper_tbis(uint64_t p) +{ + tlb_flush_page(env, p); +} #endif /*****************************************************************************/ @@ -1335,5 +1345,4 @@ void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) } env = saved_env; } - #endif diff --git a/target-alpha/translate.c b/target-alpha/translate.c index e664d62aa..ad6c2ca44 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -1621,7 +1621,6 @@ static void gen_mfpr(int ra, int regno) static void gen_mtpr(int rb, int regno) { TCGv tmp; - int data; if (rb == 31) { tmp = tcg_const_i64(0); @@ -1629,16 +1628,27 @@ static void gen_mtpr(int rb, int regno) tmp = cpu_ir[rb]; } - /* The basic registers are data only, and unknown registers - are read-zero, write-ignore. */ - data = cpu_pr_data(regno); - if (data != 0) { - if (data & PR_BYTE) { - tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE); - } else if (data & PR_LONG) { - tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG); - } else { - tcg_gen_st_i64(tmp, cpu_env, data); + /* These two register numbers perform a TLB cache flush. Thankfully we + can only do this inside PALmode, which means that the current basic + block cannot be affected by the change in mappings. */ + if (regno == 255) { + /* TBIA */ + gen_helper_tbia(); + } else if (regno == 254) { + /* TBIS */ + gen_helper_tbis(tmp); + } else { + /* The basic registers are data only, and unknown registers + are read-zero, write-ignore. */ + int data = cpu_pr_data(regno); + if (data != 0) { + if (data & PR_BYTE) { + tcg_gen_st8_i64(tmp, cpu_env, data & ~PR_BYTE); + } else if (data & PR_LONG) { + tcg_gen_st32_i64(tmp, cpu_env, data & ~PR_LONG); + } else { + tcg_gen_st_i64(tmp, cpu_env, data); + } } } |