diff options
Diffstat (limited to 'target-mips/cpu.h')
-rw-r--r-- | target-mips/cpu.h | 205 |
1 files changed, 136 insertions, 69 deletions
diff --git a/target-mips/cpu.h b/target-mips/cpu.h index 5182dc74f..866924d18 100644 --- a/target-mips/cpu.h +++ b/target-mips/cpu.h @@ -1,5 +1,5 @@ -#ifndef MIPS_CPU_H -#define MIPS_CPU_H +#if !defined (__MIPS_CPU_H__) +#define __MIPS_CPU_H__ //#define DEBUG_OP @@ -8,7 +8,6 @@ #define CPUArchState struct CPUMIPSState #include "qemu-common.h" -#include "cpu-qom.h" #include "mips-defs.h" #include "exec/cpu-defs.h" #include "fpu/softfloat.h" @@ -19,7 +18,7 @@ typedef struct r4k_tlb_t r4k_tlb_t; struct r4k_tlb_t { target_ulong VPN; uint32_t PageMask; - uint16_t ASID; + uint8_t ASID; unsigned int G:1; unsigned int C0:3; unsigned int C1:3; @@ -111,9 +110,7 @@ struct CPUMIPSFPUContext { #define FCR0_PRID 8 #define FCR0_REV 0 /* fcsr */ - uint32_t fcr31_rw_bitmask; uint32_t fcr31; -#define FCR31_FS 24 #define FCR31_ABS2008 19 #define FCR31_NAN2008 18 #define SET_FP_COND(num,env) do { ((env).fcr31) |= ((num) ? (1 << ((num) + 24)) : (1 << 23)); } while(0) @@ -343,7 +340,6 @@ struct CPUMIPSState { int32_t CP0_Count; target_ulong CP0_EntryHi; #define CP0EnHi_EHINV 10 - target_ulong CP0_EntryHi_ASID_mask; int32_t CP0_Compare; int32_t CP0_Status; #define CP0St_CU3 31 @@ -468,7 +464,6 @@ struct CPUMIPSState { int32_t CP0_Config4_rw_bitmask; #define CP0C4_M 31 #define CP0C4_IE 29 -#define CP0C4_AE 28 #define CP0C4_KScrExist 16 #define CP0C4_MMUExtDef 14 #define CP0C4_FTLBPageSize 8 @@ -505,7 +500,6 @@ struct CPUMIPSState { int CP0_LLAddr_shift; target_ulong CP0_WatchLo[8]; int32_t CP0_WatchHi[8]; -#define CP0WH_ASID 16 target_ulong CP0_XContext; int32_t CP0_Framemask; int32_t CP0_Debug; @@ -619,46 +613,9 @@ struct CPUMIPSState { void *irq[8]; QEMUTimer *timer; /* Internal timer */ MemoryRegion *itc_tag; /* ITC Configuration Tags */ - target_ulong exception_base; /* ExceptionBase input to the core */ -}; - -/** - * MIPSCPU: - * @env: #CPUMIPSState - * - * A MIPS CPU. - */ -struct MIPSCPU { - /*< private >*/ - CPUState parent_obj; - /*< public >*/ - - CPUMIPSState env; }; -static inline MIPSCPU *mips_env_get_cpu(CPUMIPSState *env) -{ - return container_of(env, MIPSCPU, env); -} - -#define ENV_GET_CPU(e) CPU(mips_env_get_cpu(e)) - -#define ENV_OFFSET offsetof(MIPSCPU, env) - -#ifndef CONFIG_USER_ONLY -extern const struct VMStateDescription vmstate_mips_cpu; -#endif - -void mips_cpu_do_interrupt(CPUState *cpu); -bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req); -void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, - int flags); -hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); -int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); -int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); -void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, - MMUAccessType access_type, - int mmu_idx, uintptr_t retaddr); +#include "cpu-qom.h" #if !defined(CONFIG_USER_ONLY) int no_mmu_map_address (CPUMIPSState *env, hwaddr *physical, int *prot, @@ -681,6 +638,7 @@ void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf); +#define cpu_exec cpu_mips_exec #define cpu_signal_handler cpu_mips_signal_handler #define cpu_list mips_cpu_list @@ -806,13 +764,13 @@ enum { */ #define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0 +int cpu_mips_exec(CPUState *cpu); void mips_tcg_init(void); MIPSCPU *cpu_mips_init(const char *cpu_model); int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc); #define cpu_init(cpu_model) CPU(cpu_mips_init(cpu_model)) bool cpu_supports_cps_smp(const char *cpu_model); -void cpu_set_exception_base(int vp_index, target_ulong address); /* TODO QOM'ify CPU reset and remove */ void cpu_state_reset(CPUMIPSState *s); @@ -831,11 +789,6 @@ void cpu_mips_soft_irq(CPUMIPSState *env, int irq, int level); /* helper.c */ int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, int mmu_idx); - -/* op_helper.c */ -uint32_t float_class_s(uint32_t arg, float_status *fst); -uint64_t float_class_d(uint64_t arg, float_status *fst); - #if !defined(CONFIG_USER_ONLY) void r4k_invalidate_tlb (CPUMIPSState *env, int idx, int use_extra); hwaddr cpu_mips_translate_address (CPUMIPSState *env, target_ulong address, @@ -855,21 +808,14 @@ static inline void restore_rounding_mode(CPUMIPSState *env) static inline void restore_flush_mode(CPUMIPSState *env) { - set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0, + set_flush_to_zero((env->active_fpu.fcr31 & (1 << 24)) != 0, &env->active_fpu.fp_status); } -static inline void restore_snan_bit_mode(CPUMIPSState *env) -{ - set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, - &env->active_fpu.fp_status); -} - static inline void restore_fp_status(CPUMIPSState *env) { restore_rounding_mode(env); restore_flush_mode(env); - restore_snan_bit_mode(env); } static inline void restore_msa_fp_status(CPUMIPSState *env) @@ -893,7 +839,7 @@ static inline void restore_pamask(CPUMIPSState *env) } static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *flags) + target_ulong *cs_base, int *flags) { *pc = env->active_tc.PC; *cs_base = 0; @@ -952,6 +898,8 @@ static inline int mips_vp_active(CPUMIPSState *env) return 1; } +#include "exec/exec-all.h" + static inline void compute_hflags(CPUMIPSState *env) { env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | @@ -1051,13 +999,132 @@ static inline void compute_hflags(CPUMIPSState *env) } } -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); +#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; -void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception, - int error_code, uintptr_t pc); + 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 */ + 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 + +static inline void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, + uint32_t exception, + int error_code, + uintptr_t pc) +{ + CPUState *cs = CPU(mips_env_get_cpu(env)); + + if (exception < EXCP_SC) { + qemu_log_mask(CPU_LOG_INT, "%s: %d %d\n", + __func__, exception, error_code); + } + cs->exception_index = exception; + env->error_code = error_code; + + cpu_loop_exit_restore(cs, pc); +} static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, uint32_t exception, @@ -1066,4 +1133,4 @@ static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, do_raise_exception_err(env, exception, 0, pc); } -#endif /* MIPS_CPU_H */ +#endif /* !defined (__MIPS_CPU_H__) */ |