summaryrefslogtreecommitdiff
path: root/target-sh4
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2010-02-02 19:50:51 +0100
committerAurelien Jarno <aurelien@aurel32.net>2010-02-09 21:08:05 +0100
commite67fcc1178d21f7cf2c3cac0916f1e4e0bed16f8 (patch)
tree3f9b7d8d03a1436c45c38256b1dc438053136ca3 /target-sh4
parent2909462215c7663d1a6cd2832a9176d0c9f4063f (diff)
downloadqemu-e67fcc1178d21f7cf2c3cac0916f1e4e0bed16f8.tar.gz
qemu-e67fcc1178d21f7cf2c3cac0916f1e4e0bed16f8.tar.bz2
qemu-e67fcc1178d21f7cf2c3cac0916f1e4e0bed16f8.zip
target-sh4: MMU: optimize UTLB accesses
With the current code, the QEMU TLB is setup to match the read/write mode of the MMU fault. This means when read access is done, the page is setup in read-only mode. When the page is later accessed in write mode, an MMU fault happened, and the page is switch in write-only mode. This flip-flop causes a lot of calls to the MMU code and slow down the emulation. This patch changes the MMU emulation, so that the QEMU TLB is setup to match the UTLB protection key. This impressively increase the speed of the emulation. Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-sh4')
-rw-r--r--target-sh4/helper.c38
1 files changed, 14 insertions, 24 deletions
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 589efe40ad..2d00dfadd4 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -386,38 +386,28 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
n = find_utlb_entry(env, address, use_asid);
if (n >= 0) {
matching = &env->utlb[n];
- switch ((matching->pr << 1) | ((env->sr & SR_MD) ? 1 : 0)) {
- case 0: /* 000 */
- case 2: /* 010 */
- n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE :
- MMU_DTLB_VIOLATION_READ;
- break;
- case 1: /* 001 */
- case 4: /* 100 */
- case 5: /* 101 */
- if (rw == 1)
- n = MMU_DTLB_VIOLATION_WRITE;
- else
- *prot = PAGE_READ;
- break;
- case 3: /* 011 */
- case 6: /* 110 */
- case 7: /* 111 */
- *prot = (rw == 1)? PAGE_WRITE : PAGE_READ;
- break;
- }
+ if (!(env->sr & SR_MD) && !(matching->pr & 2)) {
+ n = (rw == 1) ? MMU_DTLB_VIOLATION_WRITE :
+ MMU_DTLB_VIOLATION_READ;
+ } else if ((rw == 1) && !(matching->pr & 1)) {
+ n = MMU_DTLB_VIOLATION_WRITE;
+ } else if ((rw == 1) & !matching->d) {
+ n = MMU_DTLB_INITIAL_WRITE;
+ } else {
+ *prot = PAGE_READ;
+ if ((matching->pr & 1) && matching->d) {
+ *prot |= PAGE_WRITE;
+ }
+ }
} else if (n == MMU_DTLB_MISS) {
n = (rw == 1) ? MMU_DTLB_MISS_WRITE :
MMU_DTLB_MISS_READ;
}
}
if (n >= 0) {
+ n = MMU_OK;
*physical = ((matching->ppn << 10) & ~(matching->size - 1)) |
(address & (matching->size - 1));
- if ((rw == 1) & !matching->d)
- n = MMU_DTLB_INITIAL_WRITE;
- else
- n = MMU_OK;
}
return n;
}