diff options
author | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-13 10:59:14 +0000 |
---|---|---|
committer | edgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-13 10:59:14 +0000 |
commit | cf1d97f07480b6197aebc489938b4e1fed78d3e7 (patch) | |
tree | d4ae1d25078f714690f5b01761f2bffd5d57f115 /target-cris/op_helper.c | |
parent | 3bd8c5e4f1fdb61a3eb8a4a8b6e5b4cf1156ba76 (diff) |
CRIS: Improve TLB management and handle delayslots at page boundaries.
* Dont flush the entire qemu tlb when the $pid changes. Instead we go through
the guests TLB and choose entries that need to be flushed.
* Add env->dslot and handle delayslots at pageboundaries.
* Remove some unused code.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4450 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-cris/op_helper.c')
-rw-r--r-- | target-cris/op_helper.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/target-cris/op_helper.c b/target-cris/op_helper.c index 197fdcc884..ea8016b43c 100644 --- a/target-cris/op_helper.c +++ b/target-cris/op_helper.c @@ -85,6 +85,13 @@ void helper_raise_exception(uint32_t index) cpu_loop_exit(); } +void helper_tlb_flush_pid(uint32_t pid) +{ +#if !defined(CONFIG_USER_ONLY) + cris_mmu_flush_pid(env, pid); +#endif +} + void helper_tlb_flush(void) { tlb_flush(env, 1); @@ -100,6 +107,10 @@ void helper_dummy(void) } +/* Used by the tlb decoder. */ +#define EXTRACT_FIELD(src, start, end) \ + (((src) >> start) & ((1 << (end - start + 1)) - 1)) + void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) { uint32_t srs; @@ -120,10 +131,7 @@ void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) uint32_t idx; uint32_t lo, hi; uint32_t vaddr; - - vaddr = cris_mmu_tlb_latest_update(env); - D(fprintf(logfile, "tlb flush vaddr=%x\n", vaddr)); - tlb_flush_page(env, vaddr); + int tlb_v; idx = set = env->sregs[SFR_RW_MM_TLB_SEL]; set >>= 4; @@ -134,8 +142,19 @@ void helper_movl_sreg_reg (uint32_t sreg, uint32_t reg) lo = env->sregs[SFR_RW_MM_TLB_LO]; /* Writes are done via r_mm_cause. */ hi = env->sregs[SFR_R_MM_CAUSE]; + + vaddr = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].hi, + 13, 31); + vaddr <<= TARGET_PAGE_BITS; + tlb_v = EXTRACT_FIELD(env->tlbsets[srs-1][set][idx].lo, + 3, 3); env->tlbsets[srs - 1][set][idx].lo = lo; env->tlbsets[srs - 1][set][idx].hi = hi; + + D(fprintf(logfile, + "tlb flush vaddr=%x v=%d pc=%x\n", + vaddr, tlb_v, env->pc)); + tlb_flush_page(env, vaddr); } } #endif |