aboutsummaryrefslogtreecommitdiff
path: root/target-sh4/helper.c
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-09 18:45:55 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-09 18:45:55 +0000
commitea2b542a4c8fbf50a00c7b431b9fd2c0b832991f (patch)
treed98ed99a9cd142c3790daec8eedc1e36a4e88ec9 /target-sh4/helper.c
parent939ef5938fa15b996d3801fa53ef5be2f5cf3495 (diff)
SH4 MMU improvements
(Shin-ichiro KAWASAKI) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4396 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sh4/helper.c')
-rw-r--r--target-sh4/helper.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/target-sh4/helper.c b/target-sh4/helper.c
index 52bef2fca1..917f02f806 100644
--- a/target-sh4/helper.c
+++ b/target-sh4/helper.c
@@ -193,7 +193,7 @@ static void update_itlb_use(CPUState * env, int itlbnb)
switch (itlbnb) {
case 0:
- and_mask = 0x7f;
+ and_mask = 0x1f;
break;
case 1:
and_mask = 0xe7;
@@ -208,7 +208,7 @@ static void update_itlb_use(CPUState * env, int itlbnb)
break;
}
- env->mmucr &= (and_mask << 24);
+ env->mmucr &= (and_mask << 24) | 0x00ffffff;
env->mmucr |= (or_mask << 24);
}
@@ -216,7 +216,7 @@ static int itlb_replacement(CPUState * env)
{
if ((env->mmucr & 0xe0000000) == 0xe0000000)
return 0;
- if ((env->mmucr & 0x98000000) == 0x08000000)
+ if ((env->mmucr & 0x98000000) == 0x18000000)
return 1;
if ((env->mmucr & 0x54000000) == 0x04000000)
return 2;
@@ -264,7 +264,7 @@ static int find_tlb_entry(CPUState * env, target_ulong address,
start = (entries[i].vpn << 10) & ~(entries[i].size - 1);
end = start + entries[i].size - 1;
if (address >= start && address <= end) { /* Match */
- if (match != -1)
+ if (match != MMU_DTLB_MISS)
return MMU_DTLB_MULTIPLE; /* Multiple match */
match = i;
}
@@ -290,8 +290,10 @@ int find_itlb_entry(CPUState * env, target_ulong address,
n = itlb_replacement(env);
env->itlb[n] = env->utlb[e];
e = n;
- }
- }
+ } else if (e == MMU_DTLB_MISS)
+ e = MMU_ITLB_MISS;
+ } else if (e == MMU_DTLB_MISS)
+ e = MMU_ITLB_MISS;
if (e >= 0)
update_itlb_use(env, e);
return e;
@@ -418,6 +420,21 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw,
target_ulong physical, page_offset, page_size;
int prot, ret, access_type;
+ switch (rw) {
+ case 0:
+ rw = PAGE_READ;
+ break;
+ case 1:
+ rw = PAGE_WRITE;
+ break;
+ case 2: /* READ_ACCESS_TYPE == 2 defined in softmmu_template.h */
+ rw = PAGE_READ;
+ break;
+ default:
+ /* fatal error */
+ assert(0);
+ }
+
/* XXXXX */
#if 0
fprintf(stderr, "%s pc %08x ad %08x rw %d mmu_idx %d smmu %d\n",
@@ -479,4 +496,41 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr)
return physical;
}
+void cpu_load_tlb(CPUState * env)
+{
+ int n = cpu_mmucr_urc(env->mmucr);
+ tlb_t * entry = &env->utlb[n];
+
+ /* Take values into cpu status from registers. */
+ entry->asid = (uint8_t)cpu_pteh_asid(env->pteh);
+ entry->vpn = cpu_pteh_vpn(env->pteh);
+ entry->v = (uint8_t)cpu_ptel_v(env->ptel);
+ entry->ppn = cpu_ptel_ppn(env->ptel);
+ entry->sz = (uint8_t)cpu_ptel_sz(env->ptel);
+ switch (entry->sz) {
+ case 0: /* 00 */
+ entry->size = 1024; /* 1K */
+ break;
+ case 1: /* 01 */
+ entry->size = 1024 * 4; /* 4K */
+ break;
+ case 2: /* 10 */
+ entry->size = 1024 * 64; /* 64K */
+ break;
+ case 3: /* 11 */
+ entry->size = 1024 * 1024; /* 1M */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ entry->sh = (uint8_t)cpu_ptel_sh(env->ptel);
+ entry->c = (uint8_t)cpu_ptel_c(env->ptel);
+ entry->pr = (uint8_t)cpu_ptel_pr(env->ptel);
+ entry->d = (uint8_t)cpu_ptel_d(env->ptel);
+ entry->wt = (uint8_t)cpu_ptel_wt(env->ptel);
+ entry->sa = (uint8_t)cpu_ptea_sa(env->ptea);
+ entry->tc = (uint8_t)cpu_ptea_tc(env->ptea);
+}
+
#endif