X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/e40a67beeda6aa6e735546e9f08f3db41e23592a..7510454e3e74aafa2e6c50388bf24904644b6a96:/target-sh4/helper.c diff --git a/target-sh4/helper.c b/target-sh4/helper.c index bee05274fd..3f8f1fa296 100644 --- a/target-sh4/helper.c +++ b/target-sh4/helper.c @@ -24,19 +24,27 @@ #include #include "cpu.h" -#include "exec-all.h" -#include "hw/sh_intc.h" + +#if !defined(CONFIG_USER_ONLY) +#include "hw/sh4/sh_intc.h" +#endif #if defined(CONFIG_USER_ONLY) -void do_interrupt (CPUState *env) +void superh_cpu_do_interrupt(CPUState *cs) { - env->exception_index = -1; + SuperHCPU *cpu = SUPERH_CPU(cs); + CPUSH4State *env = &cpu->env; + + env->exception_index = -1; } -int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) +int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, + int mmu_idx) { + SuperHCPU *cpu = SUPERH_CPU(cs); + CPUSH4State *env = &cpu->env; + env->tea = address; env->exception_index = -1; switch (rw) { @@ -76,9 +84,11 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr) #define MMU_DADDR_ERROR_READ (-12) #define MMU_DADDR_ERROR_WRITE (-13) -void do_interrupt(CPUState * env) +void superh_cpu_do_interrupt(CPUState *cs) { - int do_irq = env->interrupt_request & CPU_INTERRUPT_HARD; + SuperHCPU *cpu = SUPERH_CPU(cs); + CPUSH4State *env = &cpu->env; + int do_irq = cs->interrupt_request & CPU_INTERRUPT_HARD; int do_exp, irq_vector = env->exception_index; /* prioritize exceptions over interrupts */ @@ -90,11 +100,11 @@ void do_interrupt(CPUState * env) if (do_exp && env->exception_index != 0x1e0) { env->exception_index = 0x000; /* masked exception -> reset */ } - if (do_irq && !env->intr_at_halt) { + if (do_irq && !env->in_sleep) { return; /* masked */ } - env->intr_at_halt = 0; } + env->in_sleep = 0; if (do_irq) { irq_vector = sh_intc_get_pending_vector(env->intc_handle, @@ -152,7 +162,7 @@ void do_interrupt(CPUState * env) } qemu_log("exception 0x%03x [%s] raised\n", irq_vector, expname); - log_cpu_state(env, 0); + log_cpu_state(cs, 0); } env->ssr = env->sr; @@ -200,7 +210,7 @@ void do_interrupt(CPUState * env) } } -static void update_itlb_use(CPUState * env, int itlbnb) +static void update_itlb_use(CPUSH4State * env, int itlbnb) { uint8_t or_mask = 0, and_mask = (uint8_t) - 1; @@ -225,7 +235,7 @@ static void update_itlb_use(CPUState * env, int itlbnb) env->mmucr |= (or_mask << 24); } -static int itlb_replacement(CPUState * env) +static int itlb_replacement(CPUSH4State * env) { if ((env->mmucr & 0xe0000000) == 0xe0000000) return 0; @@ -241,7 +251,7 @@ static int itlb_replacement(CPUState * env) /* Find the corresponding entry in the right TLB Return entry, MMU_DTLB_MISS or MMU_DTLB_MULTIPLE */ -static int find_tlb_entry(CPUState * env, target_ulong address, +static int find_tlb_entry(CPUSH4State * env, target_ulong address, tlb_t * entries, uint8_t nbtlb, int use_asid) { int match = MMU_DTLB_MISS; @@ -267,7 +277,7 @@ static int find_tlb_entry(CPUState * env, target_ulong address, return match; } -static void increment_urc(CPUState * env) +static void increment_urc(CPUSH4State * env) { uint8_t urb, urc; @@ -283,7 +293,7 @@ static void increment_urc(CPUState * env) /* Copy and utlb entry into itlb Return entry */ -static int copy_utlb_entry_itlb(CPUState *env, int utlb) +static int copy_utlb_entry_itlb(CPUSH4State *env, int utlb) { int itlb; @@ -301,7 +311,7 @@ static int copy_utlb_entry_itlb(CPUState *env, int utlb) /* Find itlb entry Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE */ -static int find_itlb_entry(CPUState * env, target_ulong address, +static int find_itlb_entry(CPUSH4State * env, target_ulong address, int use_asid) { int e; @@ -319,7 +329,7 @@ static int find_itlb_entry(CPUState * env, target_ulong address, /* Find utlb entry Return entry, MMU_DTLB_MISS, MMU_DTLB_MULTIPLE */ -static int find_utlb_entry(CPUState * env, target_ulong address, int use_asid) +static int find_utlb_entry(CPUSH4State * env, target_ulong address, int use_asid) { /* per utlb access */ increment_urc(env); @@ -335,7 +345,7 @@ static int find_utlb_entry(CPUState * env, target_ulong address, int use_asid) MMU_ITLB_MULTIPLE, MMU_ITLB_VIOLATION, MMU_IADDR_ERROR, MMU_DADDR_ERROR_READ, MMU_DADDR_ERROR_WRITE. */ -static int get_mmu_address(CPUState * env, target_ulong * physical, +static int get_mmu_address(CPUSH4State * env, target_ulong * physical, int *prot, target_ulong address, int rw, int access_type) { @@ -401,7 +411,7 @@ static int get_mmu_address(CPUState * env, target_ulong * physical, return n; } -static int get_physical_address(CPUState * env, target_ulong * physical, +static int get_physical_address(CPUSH4State * env, target_ulong * physical, int *prot, target_ulong address, int rw, int access_type) { @@ -440,9 +450,11 @@ static int get_physical_address(CPUState * env, target_ulong * physical, return get_mmu_address(env, physical, prot, address, rw, access_type); } -int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, - int mmu_idx, int is_softmmu) +int superh_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, + int mmu_idx) { + SuperHCPU *cpu = SUPERH_CPU(cs); + CPUSH4State *env = &cpu->env; target_ulong physical; int prot, ret, access_type; @@ -453,6 +465,10 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, if (ret != MMU_OK) { env->tea = address; + if (ret != MMU_DTLB_MULTIPLE && ret != MMU_ITLB_MULTIPLE) { + env->pteh = (env->pteh & PTEH_ASID_MASK) | + (address & PTEH_VPN_MASK); + } switch (ret) { case MMU_ITLB_MISS: case MMU_DTLB_MISS_READ: @@ -479,7 +495,7 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, break; case MMU_IADDR_ERROR: case MMU_DADDR_ERROR_READ: - env->exception_index = 0x0c0; + env->exception_index = 0x0e0; break; case MMU_DADDR_ERROR_WRITE: env->exception_index = 0x100; @@ -497,12 +513,13 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, return 0; } -target_phys_addr_t cpu_get_phys_page_debug(CPUState * env, target_ulong addr) +hwaddr superh_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) { + SuperHCPU *cpu = SUPERH_CPU(cs); target_ulong physical; int prot; - get_physical_address(env, &physical, &prot, addr, 0, 0); + get_physical_address(&cpu->env, &physical, &prot, addr, 0, 0); return physical; } @@ -567,14 +584,25 @@ void cpu_load_tlb(CPUSH4State * env) tlb_flush(s, 1); } -void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, +uint32_t cpu_sh4_read_mmaped_itlb_addr(CPUSH4State *s, + hwaddr 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, hwaddr addr, uint32_t mem_value) { uint32_t vpn = (mem_value & 0xfffffc00) >> 10; 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,7 +614,71 @@ void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr, entry->v = v; } -void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, +uint32_t cpu_sh4_read_mmaped_itlb_data(CPUSH4State *s, + hwaddr 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, hwaddr 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); + } +} + +uint32_t cpu_sh4_read_mmaped_utlb_addr(CPUSH4State *s, + hwaddr 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, hwaddr addr, uint32_t mem_value) { int associate = addr & 0x0000080; @@ -658,6 +750,65 @@ void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr, } } +uint32_t cpu_sh4_read_mmaped_utlb_data(CPUSH4State *s, + hwaddr 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, hwaddr 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; @@ -677,7 +828,7 @@ int cpu_sh4_is_cached(CPUSH4State * env, target_ulong addr) /* * TODO : Evaluate CCR and check if the cache is on or off. * Now CCR is not in CPUSH4State, but in SH7750State. - * When you move the ccr inot CPUSH4State, the code will be + * When you move the ccr into CPUSH4State, the code will be * as follows. */ #if 0