diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 39a73e52..6ee8aae5 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -3202,10 +3202,13 @@ mips_symbols = ( 'cpu_mips_exec', 'cpu_mips_get_random', 'cpu_mips_get_count', + 'cpu_mips_store_cause', 'cpu_mips_store_count', 'cpu_mips_store_compare', + 'cpu_mips_store_status', 'cpu_mips_start_count', 'cpu_mips_stop_count', + 'cpu_mips_tlb_flush', 'mips_machine_init', 'cpu_mips_kseg0_to_phys', 'cpu_mips_phys_to_kseg0', @@ -4120,7 +4123,8 @@ mips_symbols = ( 'mips_cpu_list', 'mips_release', 'MIPS64_REGS_STORAGE_SIZE', - 'MIPS_REGS_STORAGE_SIZE' + 'MIPS_REGS_STORAGE_SIZE', + 'sync_c0_status', ) sparc_symbols = ( diff --git a/qemu/mips.h b/qemu/mips.h index 8d30c696..10a8c237 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -3149,10 +3149,13 @@ #define cpu_mips_exec cpu_mips_exec_mips #define cpu_mips_get_random cpu_mips_get_random_mips #define cpu_mips_get_count cpu_mips_get_count_mips +#define cpu_mips_store_cause cpu_mips_store_cause_mips #define cpu_mips_store_count cpu_mips_store_count_mips #define cpu_mips_store_compare cpu_mips_store_compare_mips +#define cpu_mips_store_status cpu_mips_store_status_mips #define cpu_mips_start_count cpu_mips_start_count_mips #define cpu_mips_stop_count cpu_mips_stop_count_mips +#define cpu_mips_tlb_flush cpu_mips_tlb_flush_mips #define mips_machine_init mips_machine_init_mips #define cpu_mips_kseg0_to_phys cpu_mips_kseg0_to_phys_mips #define cpu_mips_phys_to_kseg0 cpu_mips_phys_to_kseg0_mips @@ -4068,4 +4071,5 @@ #define mips_release mips_release_mips #define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mips #define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mips +#define sync_c0_status sync_c0_status_mips #endif diff --git a/qemu/mips64.h b/qemu/mips64.h index 41a1eb2b..81f3e20b 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -3149,10 +3149,13 @@ #define cpu_mips_exec cpu_mips_exec_mips64 #define cpu_mips_get_random cpu_mips_get_random_mips64 #define cpu_mips_get_count cpu_mips_get_count_mips64 +#define cpu_mips_store_cause cpu_mips_store_cause_mips64 #define cpu_mips_store_count cpu_mips_store_count_mips64 #define cpu_mips_store_compare cpu_mips_store_compare_mips64 +#define cpu_mips_store_status cpu_mips_store_status_mips64 #define cpu_mips_start_count cpu_mips_start_count_mips64 #define cpu_mips_stop_count cpu_mips_stop_count_mips64 +#define cpu_mips_tlb_flush cpu_mips_tlb_flush_mips64 #define mips_machine_init mips_machine_init_mips64 #define cpu_mips_kseg0_to_phys cpu_mips_kseg0_to_phys_mips64 #define cpu_mips_phys_to_kseg0 cpu_mips_phys_to_kseg0_mips64 @@ -4068,4 +4071,5 @@ #define mips_release mips_release_mips64 #define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mips64 #define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mips64 +#define sync_c0_status sync_c0_status_mips64 #endif diff --git a/qemu/mips64el.h b/qemu/mips64el.h index c0c1857f..606e47bf 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -3149,10 +3149,13 @@ #define cpu_mips_exec cpu_mips_exec_mips64el #define cpu_mips_get_random cpu_mips_get_random_mips64el #define cpu_mips_get_count cpu_mips_get_count_mips64el +#define cpu_mips_store_cause cpu_mips_store_cause_mips64el #define cpu_mips_store_count cpu_mips_store_count_mips64el #define cpu_mips_store_compare cpu_mips_store_compare_mips64el +#define cpu_mips_store_status cpu_mips_store_status_mips64el #define cpu_mips_start_count cpu_mips_start_count_mips64el #define cpu_mips_stop_count cpu_mips_stop_count_mips64el +#define cpu_mips_tlb_flush cpu_mips_tlb_flush_mips64el #define mips_machine_init mips_machine_init_mips64el #define cpu_mips_kseg0_to_phys cpu_mips_kseg0_to_phys_mips64el #define cpu_mips_phys_to_kseg0 cpu_mips_phys_to_kseg0_mips64el @@ -4068,4 +4071,5 @@ #define mips_release mips_release_mips64el #define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mips64el #define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mips64el +#define sync_c0_status sync_c0_status_mips64el #endif diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 73474c88..65fce8ff 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -3149,10 +3149,13 @@ #define cpu_mips_exec cpu_mips_exec_mipsel #define cpu_mips_get_random cpu_mips_get_random_mipsel #define cpu_mips_get_count cpu_mips_get_count_mipsel +#define cpu_mips_store_cause cpu_mips_store_cause_mipsel #define cpu_mips_store_count cpu_mips_store_count_mipsel #define cpu_mips_store_compare cpu_mips_store_compare_mipsel +#define cpu_mips_store_status cpu_mips_store_status_mipsel #define cpu_mips_start_count cpu_mips_start_count_mipsel #define cpu_mips_stop_count cpu_mips_stop_count_mipsel +#define cpu_mips_tlb_flush cpu_mips_tlb_flush_mipsel #define mips_machine_init mips_machine_init_mipsel #define cpu_mips_kseg0_to_phys cpu_mips_kseg0_to_phys_mipsel #define cpu_mips_phys_to_kseg0 cpu_mips_phys_to_kseg0_mipsel @@ -4068,4 +4071,5 @@ #define mips_release mips_release_mipsel #define MIPS64_REGS_STORAGE_SIZE MIPS64_REGS_STORAGE_SIZE_mipsel #define MIPS_REGS_STORAGE_SIZE MIPS_REGS_STORAGE_SIZE_mipsel +#define sync_c0_status sync_c0_status_mipsel #endif diff --git a/qemu/target-mips/cpu.h b/qemu/target-mips/cpu.h index 3819642e..65724645 100644 --- a/qemu/target-mips/cpu.h +++ b/qemu/target-mips/cpu.h @@ -1028,117 +1028,10 @@ static inline void compute_hflags(CPUMIPSState *env) } } -#ifndef CONFIG_USER_ONLY -static inline void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global) -{ - MIPSCPU *cpu = mips_env_get_cpu(env); - - /* Flush qemu's TLB and discard all shadowed entries. */ - tlb_flush(CPU(cpu), flush_global); - env->tlb->tlb_in_use = env->tlb->nb_tlb; -} - -/* Called for updates to CP0_Status. */ -static inline void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) -{ - int32_t tcstatus, *tcst; - uint32_t v = cpu->CP0_Status; - uint32_t cu, mx, asid, ksu; - uint32_t mask = ((1 << CP0TCSt_TCU3) - | (1 << CP0TCSt_TCU2) - | (1 << CP0TCSt_TCU1) - | (1 << CP0TCSt_TCU0) - | (1 << CP0TCSt_TMX) - | (3 << CP0TCSt_TKSU) - | (0xff << CP0TCSt_TASID)); - - cu = (v >> CP0St_CU0) & 0xf; - mx = (v >> CP0St_MX) & 0x1; - ksu = (v >> CP0St_KSU) & 0x3; - asid = env->CP0_EntryHi & 0xff; - - tcstatus = cu << CP0TCSt_TCU0; - tcstatus |= mx << CP0TCSt_TMX; - tcstatus |= ksu << CP0TCSt_TKSU; - tcstatus |= asid; - - if (tc == cpu->current_tc) { - tcst = &cpu->active_tc.CP0_TCStatus; - } else { - tcst = &cpu->tcs[tc].CP0_TCStatus; - } - - *tcst &= ~mask; - *tcst |= tcstatus; - compute_hflags(cpu); -} - -static inline void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) -{ - uint32_t mask = env->CP0_Status_rw_bitmask; - target_ulong old = env->CP0_Status; - - if (env->insn_flags & ISA_MIPS32R6) { - bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3; -#if defined(TARGET_MIPS64) - uint32_t ksux = (1 << CP0St_KX) & val; - ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */ - ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */ - val = (val & ~(7 << CP0St_UX)) | ksux; -#endif - if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) { - mask &= ~(3 << CP0St_KSU); - } - mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val); - } - - env->CP0_Status = (old & ~mask) | (val & mask); -#if defined(TARGET_MIPS64) - if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) { - /* Access to at least one of the 64-bit segments has been disabled */ - cpu_mips_tlb_flush(env, 1); - } -#endif - if (env->CP0_Config3 & (1 << CP0C3_MT)) { - sync_c0_status(env, env, env->current_tc); - } else { - compute_hflags(env); - } -} - -static inline void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val) -{ - uint32_t mask = 0x00C00300; - uint32_t old = env->CP0_Cause; - //int i; - - if (env->insn_flags & ISA_MIPS32R2) { - mask |= 1 << CP0Ca_DC; - } - if (env->insn_flags & ISA_MIPS32R6) { - mask &= ~((1 << CP0Ca_WP) & val); - } - - env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask); - - if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { - if (env->CP0_Cause & (1 << CP0Ca_DC)) { - cpu_mips_stop_count(env); - } else { - cpu_mips_start_count(env); - } - } - - /* Set/reset software interrupts */ -#if 0 - for (i = 0 ; i < 2 ; i++) { - if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { - cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i))); - } - } -#endif -} -#endif +void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global); +void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc); +void cpu_mips_store_status(CPUMIPSState *env, target_ulong val); +void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val); void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception, int error_code, uintptr_t pc); diff --git a/qemu/target-mips/helper.c b/qemu/target-mips/helper.c index a9043566..8494f5a5 100644 --- a/qemu/target-mips/helper.c +++ b/qemu/target-mips/helper.c @@ -209,6 +209,116 @@ static int get_physical_address (CPUMIPSState *env, hwaddr *physical, return ret; } + +void cpu_mips_tlb_flush(CPUMIPSState *env, int flush_global) +{ + MIPSCPU *cpu = mips_env_get_cpu(env); + + /* Flush qemu's TLB and discard all shadowed entries. */ + tlb_flush(CPU(cpu), flush_global); + env->tlb->tlb_in_use = env->tlb->nb_tlb; +} + +/* Called for updates to CP0_Status. */ +void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc) +{ + int32_t tcstatus, *tcst; + uint32_t v = cpu->CP0_Status; + uint32_t cu, mx, asid, ksu; + uint32_t mask = ((1 << CP0TCSt_TCU3) + | (1 << CP0TCSt_TCU2) + | (1 << CP0TCSt_TCU1) + | (1 << CP0TCSt_TCU0) + | (1 << CP0TCSt_TMX) + | (3 << CP0TCSt_TKSU) + | (0xff << CP0TCSt_TASID)); + + cu = (v >> CP0St_CU0) & 0xf; + mx = (v >> CP0St_MX) & 0x1; + ksu = (v >> CP0St_KSU) & 0x3; + asid = env->CP0_EntryHi & 0xff; + + tcstatus = cu << CP0TCSt_TCU0; + tcstatus |= mx << CP0TCSt_TMX; + tcstatus |= ksu << CP0TCSt_TKSU; + tcstatus |= asid; + + if (tc == cpu->current_tc) { + tcst = &cpu->active_tc.CP0_TCStatus; + } else { + tcst = &cpu->tcs[tc].CP0_TCStatus; + } + + *tcst &= ~mask; + *tcst |= tcstatus; + compute_hflags(cpu); +} + +void cpu_mips_store_status(CPUMIPSState *env, target_ulong val) +{ + uint32_t mask = env->CP0_Status_rw_bitmask; + target_ulong old = env->CP0_Status; + + if (env->insn_flags & ISA_MIPS32R6) { + bool has_supervisor = extract32(mask, CP0St_KSU, 2) == 0x3; +#if defined(TARGET_MIPS64) + uint32_t ksux = (1 << CP0St_KX) & val; + ksux |= (ksux >> 1) & val; /* KX = 0 forces SX to be 0 */ + ksux |= (ksux >> 1) & val; /* SX = 0 forces UX to be 0 */ + val = (val & ~(7 << CP0St_UX)) | ksux; +#endif + if (has_supervisor && extract32(val, CP0St_KSU, 2) == 0x3) { + mask &= ~(3 << CP0St_KSU); + } + mask &= ~(((1 << CP0St_SR) | (1 << CP0St_NMI)) & val); + } + + env->CP0_Status = (old & ~mask) | (val & mask); +#if defined(TARGET_MIPS64) + if ((env->CP0_Status ^ old) & (old & (7 << CP0St_UX))) { + /* Access to at least one of the 64-bit segments has been disabled */ + cpu_mips_tlb_flush(env, 1); + } +#endif + if (env->CP0_Config3 & (1 << CP0C3_MT)) { + sync_c0_status(env, env, env->current_tc); + } else { + compute_hflags(env); + } +} + +void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val) +{ + uint32_t mask = 0x00C00300; + uint32_t old = env->CP0_Cause; + //int i; + + if (env->insn_flags & ISA_MIPS32R2) { + mask |= 1 << CP0Ca_DC; + } + if (env->insn_flags & ISA_MIPS32R6) { + mask &= ~((1 << CP0Ca_WP) & val); + } + + env->CP0_Cause = (env->CP0_Cause & ~mask) | (val & mask); + + if ((old ^ env->CP0_Cause) & (1 << CP0Ca_DC)) { + if (env->CP0_Cause & (1 << CP0Ca_DC)) { + cpu_mips_stop_count(env); + } else { + cpu_mips_start_count(env); + } + } + + /* Set/reset software interrupts */ +#if 0 + for (i = 0 ; i < 2 ; i++) { + if ((old ^ env->CP0_Cause) & (1 << (CP0Ca_IP + i))) { + cpu_mips_soft_irq(env, i, env->CP0_Cause & (1 << (CP0Ca_IP + i))); + } + } +#endif +} #endif static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,