diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2011-01-26 02:07:50 +0100 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2011-01-26 14:30:24 +0100 |
commit | 9f97309a70f12df5f9104f1fcc280bceac7ea27e (patch) | |
tree | 0ec829fa4ca9778bf34bc1768d47f638c255d71d | |
parent | 7f0958161056ae4e4794dfeb30bc57e432d6e8e5 (diff) |
sh4: implement missing mmaped TLB write functions
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r-- | hw/sh7750.c | 5 | ||||
-rw-r--r-- | target-sh4/cpu.h | 8 | ||||
-rw-r--r-- | target-sh4/helper.c | 62 |
3 files changed, 69 insertions, 6 deletions
diff --git a/hw/sh7750.c b/hw/sh7750.c index 36b702f628..f76f271105 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -673,7 +673,7 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr, cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value); break; case MM_ITLB_DATA: - /* XXXXX */ + cpu_sh4_write_mmaped_itlb_data(s->cpu, addr, mem_value); abort(); break; case MM_OCACHE_ADDR: @@ -684,8 +684,7 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr, cpu_sh4_write_mmaped_utlb_addr(s->cpu, addr, mem_value); break; case MM_UTLB_DATA: - /* XXXXX */ - abort(); + cpu_sh4_write_mmaped_utlb_data(s->cpu, addr, mem_value); break; default: abort(); diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 95df6d2a75..9eccb0cf8c 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -202,9 +202,13 @@ void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf); #if !defined(CONFIG_USER_ONLY) void cpu_sh4_invalidate_tlb(CPUSH4State *s); void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, - uint32_t mem_value); + uint32_t mem_value); +void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, + uint32_t mem_value); void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, - uint32_t mem_value); + uint32_t mem_value); +void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr, + uint32_t mem_value); #endif int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr); diff --git a/target-sh4/helper.c b/target-sh4/helper.c index 19b309b4f5..4cd42b51cb 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -574,7 +574,7 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8); uint8_t asid = (uint8_t)(mem_value & 0x000000ff); - int index = (addr & 0x00003f00) >> 8; + int index = (addr & 0x00000300) >> 8; tlb_t * entry = &s->itlb[index]; if (entry->v) { /* Overwriting valid entry in itlb. */ @@ -586,6 +586,34 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, entry->v = v; } +void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, + uint32_t mem_value) +{ + int array = (addr & 0x00800000) >> 23; + int index = (addr & 0x00000300) >> 8; + tlb_t * entry = &s->itlb[index]; + + if (array == 0) { + /* ITLB Data Array 1 */ + if (entry->v) { + /* Overwriting valid entry in utlb. */ + target_ulong address = entry->vpn << 10; + tlb_flush_page(s, address); + } + entry->ppn = (mem_value & 0x1ffffc00) >> 10; + entry->v = (mem_value & 0x00000100) >> 8; + entry->sz = (mem_value & 0x00000080) >> 6 | + (mem_value & 0x00000010) >> 4; + entry->pr = (mem_value & 0x00000040) >> 5; + entry->c = (mem_value & 0x00000008) >> 3; + entry->sh = (mem_value & 0x00000002) >> 1; + } else { + /* ITLB Data Array 2 */ + entry->tc = (mem_value & 0x00000008) >> 3; + entry->sa = (mem_value & 0x00000007); + } +} + void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { @@ -658,6 +686,38 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, } } +void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr, + uint32_t mem_value) +{ + int array = (addr & 0x00800000) >> 23; + int index = (addr & 0x00003f00) >> 8; + tlb_t * entry = &s->utlb[index]; + + increment_urc(s); /* per utlb access */ + + if (array == 0) { + /* UTLB Data Array 1 */ + if (entry->v) { + /* Overwriting valid entry in utlb. */ + target_ulong address = entry->vpn << 10; + tlb_flush_page(s, address); + } + entry->ppn = (mem_value & 0x1ffffc00) >> 10; + entry->v = (mem_value & 0x00000100) >> 8; + entry->sz = (mem_value & 0x00000080) >> 6 | + (mem_value & 0x00000010) >> 4; + entry->pr = (mem_value & 0x00000060) >> 5; + entry->c = (mem_value & 0x00000008) >> 3; + entry->d = (mem_value & 0x00000004) >> 2; + entry->sh = (mem_value & 0x00000002) >> 1; + entry->wt = (mem_value & 0x00000001); + } else { + /* UTLB Data Array 2 */ + entry->tc = (mem_value & 0x00000008) >> 3; + entry->sa = (mem_value & 0x00000007); + } +} + int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr) { int n; |