diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2011-01-26 02:16:39 +0100 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2011-01-26 14:30:24 +0100 |
commit | bc656a296885b8be7a27f49ae827298fd1b9d153 (patch) | |
tree | 838f08e3d195eb04720ba779ad7f7fdcb053b178 | |
parent | 9f97309a70f12df5f9104f1fcc280bceac7ea27e (diff) | |
download | qemu-bc656a296885b8be7a27f49ae827298fd1b9d153.zip qemu-bc656a296885b8be7a27f49ae827298fd1b9d153.tar.gz qemu-bc656a296885b8be7a27f49ae827298fd1b9d153.tar.bz2 |
sh4: implement missing mmaped TLB read functions
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
-rw-r--r-- | hw/sh7750.c | 15 | ||||
-rw-r--r-- | target-sh4/cpu.h | 8 | ||||
-rw-r--r-- | target-sh4/helper.c | 74 |
3 files changed, 91 insertions, 6 deletions
diff --git a/hw/sh7750.c b/hw/sh7750.c index f76f271..19d5bf8 100644 --- a/hw/sh7750.c +++ b/hw/sh7750.c @@ -625,6 +625,7 @@ static uint32_t invalid_read(void *opaque, target_phys_addr_t addr) static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr) { + SH7750State *s = opaque; uint32_t ret = 0; switch (MM_REGION_TYPE(addr)) { @@ -633,19 +634,21 @@ static uint32_t sh7750_mmct_readl(void *opaque, target_phys_addr_t addr) /* do nothing */ break; case MM_ITLB_ADDR: + ret = cpu_sh4_read_mmaped_itlb_addr(s->cpu, addr); + break; case MM_ITLB_DATA: - /* XXXXX */ - abort(); - break; + ret = cpu_sh4_read_mmaped_itlb_data(s->cpu, addr); + break; case MM_OCACHE_ADDR: case MM_OCACHE_DATA: /* do nothing */ break; case MM_UTLB_ADDR: + ret = cpu_sh4_read_mmaped_utlb_addr(s->cpu, addr); + break; case MM_UTLB_DATA: - /* XXXXX */ - abort(); - break; + ret = cpu_sh4_read_mmaped_utlb_data(s->cpu, addr); + break; default: abort(); } diff --git a/target-sh4/cpu.h b/target-sh4/cpu.h index 9eccb0c..789d188 100644 --- a/target-sh4/cpu.h +++ b/target-sh4/cpu.h @@ -201,12 +201,20 @@ void do_interrupt(CPUSH4State * env); void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf); #if !defined(CONFIG_USER_ONLY) void cpu_sh4_invalidate_tlb(CPUSH4State *s); +uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, + target_phys_addr_t addr); void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value); +uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s, + target_phys_addr_t addr); void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value); +uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, + target_phys_addr_t addr); void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value); +uint32_t cpu_sh4_read_mmaped_utlb_data(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); #endif diff --git a/target-sh4/helper.c b/target-sh4/helper.c index 4cd42b5..785e9e54 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -567,6 +567,17 @@ void cpu_load_tlb(CPUSH4State * env) tlb_flush(s, 1); } +uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, + target_phys_addr_t addr) +{ + int index = (addr & 0x00000300) >> 8; + tlb_t * entry = &s->itlb[index]; + + return (entry->vpn << 10) | + (entry->v << 8) | + (entry->asid); +} + void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { @@ -586,6 +597,29 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, entry->v = v; } +uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s, + target_phys_addr_t addr) +{ + int array = (addr & 0x00800000) >> 23; + int index = (addr & 0x00000300) >> 8; + tlb_t * entry = &s->itlb[index]; + + if (array == 0) { + /* ITLB Data Array 1 */ + return (entry->ppn << 10) | + (entry->v << 8) | + (entry->pr << 5) | + ((entry->sz & 1) << 6) | + ((entry->sz & 2) << 4) | + (entry->c << 3) | + (entry->sh << 1); + } else { + /* ITLB Data Array 2 */ + return (entry->tc << 1) | + (entry->sa); + } +} + void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { @@ -614,6 +648,19 @@ void cpu_sh4_write_mmaped_itlb_data(CPUSH4State *s, target_phys_addr_t addr, } } +uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, + target_phys_addr_t addr) +{ + int index = (addr & 0x00003f00) >> 8; + tlb_t * entry = &s->utlb[index]; + + increment_urc(s); /* per utlb access */ + + return (entry->vpn << 10) | + (entry->v << 8) | + (entry->asid); +} + void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { @@ -686,6 +733,33 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, } } +uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s, + target_phys_addr_t addr) +{ + 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) { + /* ITLB Data Array 1 */ + return (entry->ppn << 10) | + (entry->v << 8) | + (entry->pr << 5) | + ((entry->sz & 1) << 6) | + ((entry->sz & 2) << 4) | + (entry->c << 3) | + (entry->d << 2) | + (entry->sh << 1) | + (entry->wt); + } else { + /* ITLB Data Array 2 */ + return (entry->tc << 1) | + (entry->sa); + } +} + void cpu_sh4_write_mmaped_utlb_data(CPUSH4State *s, target_phys_addr_t addr, uint32_t mem_value) { |