summaryrefslogtreecommitdiff
path: root/target-cris/op_helper.c
diff options
context:
space:
mode:
authoredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-13 10:59:14 +0000
committeredgar_igl <edgar_igl@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-13 10:59:14 +0000
commitcf1d97f07480b6197aebc489938b4e1fed78d3e7 (patch)
treed4ae1d25078f714690f5b01761f2bffd5d57f115 /target-cris/op_helper.c
parent3bd8c5e4f1fdb61a3eb8a4a8b6e5b4cf1156ba76 (diff)
downloadqemu-cf1d97f07480b6197aebc489938b4e1fed78d3e7.tar.gz
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.c27
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