aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2011-01-26 02:07:50 +0100
committerAurelien Jarno <aurelien@aurel32.net>2011-01-26 14:30:24 +0100
commit9f97309a70f12df5f9104f1fcc280bceac7ea27e (patch)
tree0ec829fa4ca9778bf34bc1768d47f638c255d71d
parent7f0958161056ae4e4794dfeb30bc57e432d6e8e5 (diff)
sh4: implement missing mmaped TLB write functions
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r--hw/sh7750.c5
-rw-r--r--target-sh4/cpu.h8
-rw-r--r--target-sh4/helper.c62
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;