1*26aa3d9aSPhilippe Mathieu-Daudé /* mips internal definitions and helpers 2*26aa3d9aSPhilippe Mathieu-Daudé * 3*26aa3d9aSPhilippe Mathieu-Daudé * This work is licensed under the terms of the GNU GPL, version 2 or later. 4*26aa3d9aSPhilippe Mathieu-Daudé * See the COPYING file in the top-level directory. 5*26aa3d9aSPhilippe Mathieu-Daudé */ 6*26aa3d9aSPhilippe Mathieu-Daudé 7*26aa3d9aSPhilippe Mathieu-Daudé #ifndef MIPS_INTERNAL_H 8*26aa3d9aSPhilippe Mathieu-Daudé #define MIPS_INTERNAL_H 9*26aa3d9aSPhilippe Mathieu-Daudé 10*26aa3d9aSPhilippe Mathieu-Daudé enum CPUMIPSMSADataFormat { 11*26aa3d9aSPhilippe Mathieu-Daudé DF_BYTE = 0, 12*26aa3d9aSPhilippe Mathieu-Daudé DF_HALF, 13*26aa3d9aSPhilippe Mathieu-Daudé DF_WORD, 14*26aa3d9aSPhilippe Mathieu-Daudé DF_DOUBLE 15*26aa3d9aSPhilippe Mathieu-Daudé }; 16*26aa3d9aSPhilippe Mathieu-Daudé 17*26aa3d9aSPhilippe Mathieu-Daudé void mips_cpu_do_interrupt(CPUState *cpu); 18*26aa3d9aSPhilippe Mathieu-Daudé bool mips_cpu_exec_interrupt(CPUState *cpu, int int_req); 19*26aa3d9aSPhilippe Mathieu-Daudé void mips_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf, 20*26aa3d9aSPhilippe Mathieu-Daudé int flags); 21*26aa3d9aSPhilippe Mathieu-Daudé hwaddr mips_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); 22*26aa3d9aSPhilippe Mathieu-Daudé int mips_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg); 23*26aa3d9aSPhilippe Mathieu-Daudé int mips_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); 24*26aa3d9aSPhilippe Mathieu-Daudé void mips_cpu_do_unaligned_access(CPUState *cpu, vaddr addr, 25*26aa3d9aSPhilippe Mathieu-Daudé MMUAccessType access_type, 26*26aa3d9aSPhilippe Mathieu-Daudé int mmu_idx, uintptr_t retaddr); 27*26aa3d9aSPhilippe Mathieu-Daudé 28*26aa3d9aSPhilippe Mathieu-Daudé #if !defined(CONFIG_USER_ONLY) 29*26aa3d9aSPhilippe Mathieu-Daudé 30*26aa3d9aSPhilippe Mathieu-Daudé typedef struct r4k_tlb_t r4k_tlb_t; 31*26aa3d9aSPhilippe Mathieu-Daudé struct r4k_tlb_t { 32*26aa3d9aSPhilippe Mathieu-Daudé target_ulong VPN; 33*26aa3d9aSPhilippe Mathieu-Daudé uint32_t PageMask; 34*26aa3d9aSPhilippe Mathieu-Daudé uint16_t ASID; 35*26aa3d9aSPhilippe Mathieu-Daudé unsigned int G:1; 36*26aa3d9aSPhilippe Mathieu-Daudé unsigned int C0:3; 37*26aa3d9aSPhilippe Mathieu-Daudé unsigned int C1:3; 38*26aa3d9aSPhilippe Mathieu-Daudé unsigned int V0:1; 39*26aa3d9aSPhilippe Mathieu-Daudé unsigned int V1:1; 40*26aa3d9aSPhilippe Mathieu-Daudé unsigned int D0:1; 41*26aa3d9aSPhilippe Mathieu-Daudé unsigned int D1:1; 42*26aa3d9aSPhilippe Mathieu-Daudé unsigned int XI0:1; 43*26aa3d9aSPhilippe Mathieu-Daudé unsigned int XI1:1; 44*26aa3d9aSPhilippe Mathieu-Daudé unsigned int RI0:1; 45*26aa3d9aSPhilippe Mathieu-Daudé unsigned int RI1:1; 46*26aa3d9aSPhilippe Mathieu-Daudé unsigned int EHINV:1; 47*26aa3d9aSPhilippe Mathieu-Daudé uint64_t PFN[2]; 48*26aa3d9aSPhilippe Mathieu-Daudé }; 49*26aa3d9aSPhilippe Mathieu-Daudé 50*26aa3d9aSPhilippe Mathieu-Daudé struct CPUMIPSTLBContext { 51*26aa3d9aSPhilippe Mathieu-Daudé uint32_t nb_tlb; 52*26aa3d9aSPhilippe Mathieu-Daudé uint32_t tlb_in_use; 53*26aa3d9aSPhilippe Mathieu-Daudé int (*map_address)(struct CPUMIPSState *env, hwaddr *physical, int *prot, 54*26aa3d9aSPhilippe Mathieu-Daudé target_ulong address, int rw, int access_type); 55*26aa3d9aSPhilippe Mathieu-Daudé void (*helper_tlbwi)(struct CPUMIPSState *env); 56*26aa3d9aSPhilippe Mathieu-Daudé void (*helper_tlbwr)(struct CPUMIPSState *env); 57*26aa3d9aSPhilippe Mathieu-Daudé void (*helper_tlbp)(struct CPUMIPSState *env); 58*26aa3d9aSPhilippe Mathieu-Daudé void (*helper_tlbr)(struct CPUMIPSState *env); 59*26aa3d9aSPhilippe Mathieu-Daudé void (*helper_tlbinv)(struct CPUMIPSState *env); 60*26aa3d9aSPhilippe Mathieu-Daudé void (*helper_tlbinvf)(struct CPUMIPSState *env); 61*26aa3d9aSPhilippe Mathieu-Daudé union { 62*26aa3d9aSPhilippe Mathieu-Daudé struct { 63*26aa3d9aSPhilippe Mathieu-Daudé r4k_tlb_t tlb[MIPS_TLB_MAX]; 64*26aa3d9aSPhilippe Mathieu-Daudé } r4k; 65*26aa3d9aSPhilippe Mathieu-Daudé } mmu; 66*26aa3d9aSPhilippe Mathieu-Daudé }; 67*26aa3d9aSPhilippe Mathieu-Daudé 68*26aa3d9aSPhilippe Mathieu-Daudé int no_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, 69*26aa3d9aSPhilippe Mathieu-Daudé target_ulong address, int rw, int access_type); 70*26aa3d9aSPhilippe Mathieu-Daudé int fixed_mmu_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, 71*26aa3d9aSPhilippe Mathieu-Daudé target_ulong address, int rw, int access_type); 72*26aa3d9aSPhilippe Mathieu-Daudé int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot, 73*26aa3d9aSPhilippe Mathieu-Daudé target_ulong address, int rw, int access_type); 74*26aa3d9aSPhilippe Mathieu-Daudé void r4k_helper_tlbwi(CPUMIPSState *env); 75*26aa3d9aSPhilippe Mathieu-Daudé void r4k_helper_tlbwr(CPUMIPSState *env); 76*26aa3d9aSPhilippe Mathieu-Daudé void r4k_helper_tlbp(CPUMIPSState *env); 77*26aa3d9aSPhilippe Mathieu-Daudé void r4k_helper_tlbr(CPUMIPSState *env); 78*26aa3d9aSPhilippe Mathieu-Daudé void r4k_helper_tlbinv(CPUMIPSState *env); 79*26aa3d9aSPhilippe Mathieu-Daudé void r4k_helper_tlbinvf(CPUMIPSState *env); 80*26aa3d9aSPhilippe Mathieu-Daudé void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra); 81*26aa3d9aSPhilippe Mathieu-Daudé 82*26aa3d9aSPhilippe Mathieu-Daudé void mips_cpu_unassigned_access(CPUState *cpu, hwaddr addr, 83*26aa3d9aSPhilippe Mathieu-Daudé bool is_write, bool is_exec, int unused, 84*26aa3d9aSPhilippe Mathieu-Daudé unsigned size); 85*26aa3d9aSPhilippe Mathieu-Daudé hwaddr cpu_mips_translate_address(CPUMIPSState *env, target_ulong address, 86*26aa3d9aSPhilippe Mathieu-Daudé int rw); 87*26aa3d9aSPhilippe Mathieu-Daudé #endif 88*26aa3d9aSPhilippe Mathieu-Daudé 89*26aa3d9aSPhilippe Mathieu-Daudé #define cpu_signal_handler cpu_mips_signal_handler 90*26aa3d9aSPhilippe Mathieu-Daudé 91*26aa3d9aSPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY 92*26aa3d9aSPhilippe Mathieu-Daudé extern const struct VMStateDescription vmstate_mips_cpu; 93*26aa3d9aSPhilippe Mathieu-Daudé #endif 94*26aa3d9aSPhilippe Mathieu-Daudé 95*26aa3d9aSPhilippe Mathieu-Daudé static inline bool cpu_mips_hw_interrupts_enabled(CPUMIPSState *env) 96*26aa3d9aSPhilippe Mathieu-Daudé { 97*26aa3d9aSPhilippe Mathieu-Daudé return (env->CP0_Status & (1 << CP0St_IE)) && 98*26aa3d9aSPhilippe Mathieu-Daudé !(env->CP0_Status & (1 << CP0St_EXL)) && 99*26aa3d9aSPhilippe Mathieu-Daudé !(env->CP0_Status & (1 << CP0St_ERL)) && 100*26aa3d9aSPhilippe Mathieu-Daudé !(env->hflags & MIPS_HFLAG_DM) && 101*26aa3d9aSPhilippe Mathieu-Daudé /* Note that the TCStatus IXMT field is initialized to zero, 102*26aa3d9aSPhilippe Mathieu-Daudé and only MT capable cores can set it to one. So we don't 103*26aa3d9aSPhilippe Mathieu-Daudé need to check for MT capabilities here. */ 104*26aa3d9aSPhilippe Mathieu-Daudé !(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_IXMT)); 105*26aa3d9aSPhilippe Mathieu-Daudé } 106*26aa3d9aSPhilippe Mathieu-Daudé 107*26aa3d9aSPhilippe Mathieu-Daudé /* Check if there is pending and not masked out interrupt */ 108*26aa3d9aSPhilippe Mathieu-Daudé static inline bool cpu_mips_hw_interrupts_pending(CPUMIPSState *env) 109*26aa3d9aSPhilippe Mathieu-Daudé { 110*26aa3d9aSPhilippe Mathieu-Daudé int32_t pending; 111*26aa3d9aSPhilippe Mathieu-Daudé int32_t status; 112*26aa3d9aSPhilippe Mathieu-Daudé bool r; 113*26aa3d9aSPhilippe Mathieu-Daudé 114*26aa3d9aSPhilippe Mathieu-Daudé pending = env->CP0_Cause & CP0Ca_IP_mask; 115*26aa3d9aSPhilippe Mathieu-Daudé status = env->CP0_Status & CP0Ca_IP_mask; 116*26aa3d9aSPhilippe Mathieu-Daudé 117*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Config3 & (1 << CP0C3_VEIC)) { 118*26aa3d9aSPhilippe Mathieu-Daudé /* A MIPS configured with a vectorizing external interrupt controller 119*26aa3d9aSPhilippe Mathieu-Daudé will feed a vector into the Cause pending lines. The core treats 120*26aa3d9aSPhilippe Mathieu-Daudé the status lines as a vector level, not as indiviual masks. */ 121*26aa3d9aSPhilippe Mathieu-Daudé r = pending > status; 122*26aa3d9aSPhilippe Mathieu-Daudé } else { 123*26aa3d9aSPhilippe Mathieu-Daudé /* A MIPS configured with compatibility or VInt (Vectored Interrupts) 124*26aa3d9aSPhilippe Mathieu-Daudé treats the pending lines as individual interrupt lines, the status 125*26aa3d9aSPhilippe Mathieu-Daudé lines are individual masks. */ 126*26aa3d9aSPhilippe Mathieu-Daudé r = (pending & status) != 0; 127*26aa3d9aSPhilippe Mathieu-Daudé } 128*26aa3d9aSPhilippe Mathieu-Daudé return r; 129*26aa3d9aSPhilippe Mathieu-Daudé } 130*26aa3d9aSPhilippe Mathieu-Daudé 131*26aa3d9aSPhilippe Mathieu-Daudé void mips_tcg_init(void); 132*26aa3d9aSPhilippe Mathieu-Daudé 133*26aa3d9aSPhilippe Mathieu-Daudé /* TODO QOM'ify CPU reset and remove */ 134*26aa3d9aSPhilippe Mathieu-Daudé void cpu_state_reset(CPUMIPSState *s); 135*26aa3d9aSPhilippe Mathieu-Daudé 136*26aa3d9aSPhilippe Mathieu-Daudé /* cp0_timer.c */ 137*26aa3d9aSPhilippe Mathieu-Daudé uint32_t cpu_mips_get_random(CPUMIPSState *env); 138*26aa3d9aSPhilippe Mathieu-Daudé uint32_t cpu_mips_get_count(CPUMIPSState *env); 139*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_store_count(CPUMIPSState *env, uint32_t value); 140*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_store_compare(CPUMIPSState *env, uint32_t value); 141*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_start_count(CPUMIPSState *env); 142*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_stop_count(CPUMIPSState *env); 143*26aa3d9aSPhilippe Mathieu-Daudé 144*26aa3d9aSPhilippe Mathieu-Daudé /* helper.c */ 145*26aa3d9aSPhilippe Mathieu-Daudé int mips_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw, 146*26aa3d9aSPhilippe Mathieu-Daudé int mmu_idx); 147*26aa3d9aSPhilippe Mathieu-Daudé 148*26aa3d9aSPhilippe Mathieu-Daudé /* op_helper.c */ 149*26aa3d9aSPhilippe Mathieu-Daudé uint32_t float_class_s(uint32_t arg, float_status *fst); 150*26aa3d9aSPhilippe Mathieu-Daudé uint64_t float_class_d(uint64_t arg, float_status *fst); 151*26aa3d9aSPhilippe Mathieu-Daudé 152*26aa3d9aSPhilippe Mathieu-Daudé extern unsigned int ieee_rm[]; 153*26aa3d9aSPhilippe Mathieu-Daudé int ieee_ex_to_mips(int xcpt); 154*26aa3d9aSPhilippe Mathieu-Daudé 155*26aa3d9aSPhilippe Mathieu-Daudé static inline void restore_rounding_mode(CPUMIPSState *env) 156*26aa3d9aSPhilippe Mathieu-Daudé { 157*26aa3d9aSPhilippe Mathieu-Daudé set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], 158*26aa3d9aSPhilippe Mathieu-Daudé &env->active_fpu.fp_status); 159*26aa3d9aSPhilippe Mathieu-Daudé } 160*26aa3d9aSPhilippe Mathieu-Daudé 161*26aa3d9aSPhilippe Mathieu-Daudé static inline void restore_flush_mode(CPUMIPSState *env) 162*26aa3d9aSPhilippe Mathieu-Daudé { 163*26aa3d9aSPhilippe Mathieu-Daudé set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0, 164*26aa3d9aSPhilippe Mathieu-Daudé &env->active_fpu.fp_status); 165*26aa3d9aSPhilippe Mathieu-Daudé } 166*26aa3d9aSPhilippe Mathieu-Daudé 167*26aa3d9aSPhilippe Mathieu-Daudé static inline void restore_fp_status(CPUMIPSState *env) 168*26aa3d9aSPhilippe Mathieu-Daudé { 169*26aa3d9aSPhilippe Mathieu-Daudé restore_rounding_mode(env); 170*26aa3d9aSPhilippe Mathieu-Daudé restore_flush_mode(env); 171*26aa3d9aSPhilippe Mathieu-Daudé restore_snan_bit_mode(env); 172*26aa3d9aSPhilippe Mathieu-Daudé } 173*26aa3d9aSPhilippe Mathieu-Daudé 174*26aa3d9aSPhilippe Mathieu-Daudé static inline void restore_msa_fp_status(CPUMIPSState *env) 175*26aa3d9aSPhilippe Mathieu-Daudé { 176*26aa3d9aSPhilippe Mathieu-Daudé float_status *status = &env->active_tc.msa_fp_status; 177*26aa3d9aSPhilippe Mathieu-Daudé int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM; 178*26aa3d9aSPhilippe Mathieu-Daudé bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0; 179*26aa3d9aSPhilippe Mathieu-Daudé 180*26aa3d9aSPhilippe Mathieu-Daudé set_float_rounding_mode(ieee_rm[rounding_mode], status); 181*26aa3d9aSPhilippe Mathieu-Daudé set_flush_to_zero(flush_to_zero, status); 182*26aa3d9aSPhilippe Mathieu-Daudé set_flush_inputs_to_zero(flush_to_zero, status); 183*26aa3d9aSPhilippe Mathieu-Daudé } 184*26aa3d9aSPhilippe Mathieu-Daudé 185*26aa3d9aSPhilippe Mathieu-Daudé static inline void restore_pamask(CPUMIPSState *env) 186*26aa3d9aSPhilippe Mathieu-Daudé { 187*26aa3d9aSPhilippe Mathieu-Daudé if (env->hflags & MIPS_HFLAG_ELPA) { 188*26aa3d9aSPhilippe Mathieu-Daudé env->PAMask = (1ULL << env->PABITS) - 1; 189*26aa3d9aSPhilippe Mathieu-Daudé } else { 190*26aa3d9aSPhilippe Mathieu-Daudé env->PAMask = PAMASK_BASE; 191*26aa3d9aSPhilippe Mathieu-Daudé } 192*26aa3d9aSPhilippe Mathieu-Daudé } 193*26aa3d9aSPhilippe Mathieu-Daudé 194*26aa3d9aSPhilippe Mathieu-Daudé static inline int mips_vpe_active(CPUMIPSState *env) 195*26aa3d9aSPhilippe Mathieu-Daudé { 196*26aa3d9aSPhilippe Mathieu-Daudé int active = 1; 197*26aa3d9aSPhilippe Mathieu-Daudé 198*26aa3d9aSPhilippe Mathieu-Daudé /* Check that the VPE is enabled. */ 199*26aa3d9aSPhilippe Mathieu-Daudé if (!(env->mvp->CP0_MVPControl & (1 << CP0MVPCo_EVP))) { 200*26aa3d9aSPhilippe Mathieu-Daudé active = 0; 201*26aa3d9aSPhilippe Mathieu-Daudé } 202*26aa3d9aSPhilippe Mathieu-Daudé /* Check that the VPE is activated. */ 203*26aa3d9aSPhilippe Mathieu-Daudé if (!(env->CP0_VPEConf0 & (1 << CP0VPEC0_VPA))) { 204*26aa3d9aSPhilippe Mathieu-Daudé active = 0; 205*26aa3d9aSPhilippe Mathieu-Daudé } 206*26aa3d9aSPhilippe Mathieu-Daudé 207*26aa3d9aSPhilippe Mathieu-Daudé /* Now verify that there are active thread contexts in the VPE. 208*26aa3d9aSPhilippe Mathieu-Daudé 209*26aa3d9aSPhilippe Mathieu-Daudé This assumes the CPU model will internally reschedule threads 210*26aa3d9aSPhilippe Mathieu-Daudé if the active one goes to sleep. If there are no threads available 211*26aa3d9aSPhilippe Mathieu-Daudé the active one will be in a sleeping state, and we can turn off 212*26aa3d9aSPhilippe Mathieu-Daudé the entire VPE. */ 213*26aa3d9aSPhilippe Mathieu-Daudé if (!(env->active_tc.CP0_TCStatus & (1 << CP0TCSt_A))) { 214*26aa3d9aSPhilippe Mathieu-Daudé /* TC is not activated. */ 215*26aa3d9aSPhilippe Mathieu-Daudé active = 0; 216*26aa3d9aSPhilippe Mathieu-Daudé } 217*26aa3d9aSPhilippe Mathieu-Daudé if (env->active_tc.CP0_TCHalt & 1) { 218*26aa3d9aSPhilippe Mathieu-Daudé /* TC is in halt state. */ 219*26aa3d9aSPhilippe Mathieu-Daudé active = 0; 220*26aa3d9aSPhilippe Mathieu-Daudé } 221*26aa3d9aSPhilippe Mathieu-Daudé 222*26aa3d9aSPhilippe Mathieu-Daudé return active; 223*26aa3d9aSPhilippe Mathieu-Daudé } 224*26aa3d9aSPhilippe Mathieu-Daudé 225*26aa3d9aSPhilippe Mathieu-Daudé static inline int mips_vp_active(CPUMIPSState *env) 226*26aa3d9aSPhilippe Mathieu-Daudé { 227*26aa3d9aSPhilippe Mathieu-Daudé CPUState *other_cs = first_cpu; 228*26aa3d9aSPhilippe Mathieu-Daudé 229*26aa3d9aSPhilippe Mathieu-Daudé /* Check if the VP disabled other VPs (which means the VP is enabled) */ 230*26aa3d9aSPhilippe Mathieu-Daudé if ((env->CP0_VPControl >> CP0VPCtl_DIS) & 1) { 231*26aa3d9aSPhilippe Mathieu-Daudé return 1; 232*26aa3d9aSPhilippe Mathieu-Daudé } 233*26aa3d9aSPhilippe Mathieu-Daudé 234*26aa3d9aSPhilippe Mathieu-Daudé /* Check if the virtual processor is disabled due to a DVP */ 235*26aa3d9aSPhilippe Mathieu-Daudé CPU_FOREACH(other_cs) { 236*26aa3d9aSPhilippe Mathieu-Daudé MIPSCPU *other_cpu = MIPS_CPU(other_cs); 237*26aa3d9aSPhilippe Mathieu-Daudé if ((&other_cpu->env != env) && 238*26aa3d9aSPhilippe Mathieu-Daudé ((other_cpu->env.CP0_VPControl >> CP0VPCtl_DIS) & 1)) { 239*26aa3d9aSPhilippe Mathieu-Daudé return 0; 240*26aa3d9aSPhilippe Mathieu-Daudé } 241*26aa3d9aSPhilippe Mathieu-Daudé } 242*26aa3d9aSPhilippe Mathieu-Daudé return 1; 243*26aa3d9aSPhilippe Mathieu-Daudé } 244*26aa3d9aSPhilippe Mathieu-Daudé 245*26aa3d9aSPhilippe Mathieu-Daudé static inline void compute_hflags(CPUMIPSState *env) 246*26aa3d9aSPhilippe Mathieu-Daudé { 247*26aa3d9aSPhilippe Mathieu-Daudé env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | 248*26aa3d9aSPhilippe Mathieu-Daudé MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU | 249*26aa3d9aSPhilippe Mathieu-Daudé MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 | 250*26aa3d9aSPhilippe Mathieu-Daudé MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE | 251*26aa3d9aSPhilippe Mathieu-Daudé MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL); 252*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_ERL)) { 253*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_ERL; 254*26aa3d9aSPhilippe Mathieu-Daudé } 255*26aa3d9aSPhilippe Mathieu-Daudé if (!(env->CP0_Status & (1 << CP0St_EXL)) && 256*26aa3d9aSPhilippe Mathieu-Daudé !(env->CP0_Status & (1 << CP0St_ERL)) && 257*26aa3d9aSPhilippe Mathieu-Daudé !(env->hflags & MIPS_HFLAG_DM)) { 258*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= (env->CP0_Status >> CP0St_KSU) & MIPS_HFLAG_KSU; 259*26aa3d9aSPhilippe Mathieu-Daudé } 260*26aa3d9aSPhilippe Mathieu-Daudé #if defined(TARGET_MIPS64) 261*26aa3d9aSPhilippe Mathieu-Daudé if ((env->insn_flags & ISA_MIPS3) && 262*26aa3d9aSPhilippe Mathieu-Daudé (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_UM) || 263*26aa3d9aSPhilippe Mathieu-Daudé (env->CP0_Status & (1 << CP0St_PX)) || 264*26aa3d9aSPhilippe Mathieu-Daudé (env->CP0_Status & (1 << CP0St_UX)))) { 265*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_64; 266*26aa3d9aSPhilippe Mathieu-Daudé } 267*26aa3d9aSPhilippe Mathieu-Daudé 268*26aa3d9aSPhilippe Mathieu-Daudé if (!(env->insn_flags & ISA_MIPS3)) { 269*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_AWRAP; 270*26aa3d9aSPhilippe Mathieu-Daudé } else if (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) && 271*26aa3d9aSPhilippe Mathieu-Daudé !(env->CP0_Status & (1 << CP0St_UX))) { 272*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_AWRAP; 273*26aa3d9aSPhilippe Mathieu-Daudé } else if (env->insn_flags & ISA_MIPS64R6) { 274*26aa3d9aSPhilippe Mathieu-Daudé /* Address wrapping for Supervisor and Kernel is specified in R6 */ 275*26aa3d9aSPhilippe Mathieu-Daudé if ((((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_SM) && 276*26aa3d9aSPhilippe Mathieu-Daudé !(env->CP0_Status & (1 << CP0St_SX))) || 277*26aa3d9aSPhilippe Mathieu-Daudé (((env->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_KM) && 278*26aa3d9aSPhilippe Mathieu-Daudé !(env->CP0_Status & (1 << CP0St_KX)))) { 279*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_AWRAP; 280*26aa3d9aSPhilippe Mathieu-Daudé } 281*26aa3d9aSPhilippe Mathieu-Daudé } 282*26aa3d9aSPhilippe Mathieu-Daudé #endif 283*26aa3d9aSPhilippe Mathieu-Daudé if (((env->CP0_Status & (1 << CP0St_CU0)) && 284*26aa3d9aSPhilippe Mathieu-Daudé !(env->insn_flags & ISA_MIPS32R6)) || 285*26aa3d9aSPhilippe Mathieu-Daudé !(env->hflags & MIPS_HFLAG_KSU)) { 286*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_CP0; 287*26aa3d9aSPhilippe Mathieu-Daudé } 288*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_CU1)) { 289*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_FPU; 290*26aa3d9aSPhilippe Mathieu-Daudé } 291*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_FR)) { 292*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_F64; 293*26aa3d9aSPhilippe Mathieu-Daudé } 294*26aa3d9aSPhilippe Mathieu-Daudé if (((env->hflags & MIPS_HFLAG_KSU) != MIPS_HFLAG_KM) && 295*26aa3d9aSPhilippe Mathieu-Daudé (env->CP0_Config5 & (1 << CP0C5_SBRI))) { 296*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_SBRI; 297*26aa3d9aSPhilippe Mathieu-Daudé } 298*26aa3d9aSPhilippe Mathieu-Daudé if (env->insn_flags & ASE_DSPR2) { 299*26aa3d9aSPhilippe Mathieu-Daudé /* Enables access MIPS DSP resources, now our cpu is DSP ASER2, 300*26aa3d9aSPhilippe Mathieu-Daudé so enable to access DSPR2 resources. */ 301*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_MX)) { 302*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2; 303*26aa3d9aSPhilippe Mathieu-Daudé } 304*26aa3d9aSPhilippe Mathieu-Daudé 305*26aa3d9aSPhilippe Mathieu-Daudé } else if (env->insn_flags & ASE_DSP) { 306*26aa3d9aSPhilippe Mathieu-Daudé /* Enables access MIPS DSP resources, now our cpu is DSP ASE, 307*26aa3d9aSPhilippe Mathieu-Daudé so enable to access DSP resources. */ 308*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Status & (1 << CP0St_MX)) { 309*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_DSP; 310*26aa3d9aSPhilippe Mathieu-Daudé } 311*26aa3d9aSPhilippe Mathieu-Daudé 312*26aa3d9aSPhilippe Mathieu-Daudé } 313*26aa3d9aSPhilippe Mathieu-Daudé if (env->insn_flags & ISA_MIPS32R2) { 314*26aa3d9aSPhilippe Mathieu-Daudé if (env->active_fpu.fcr0 & (1 << FCR0_F64)) { 315*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_COP1X; 316*26aa3d9aSPhilippe Mathieu-Daudé } 317*26aa3d9aSPhilippe Mathieu-Daudé } else if (env->insn_flags & ISA_MIPS32) { 318*26aa3d9aSPhilippe Mathieu-Daudé if (env->hflags & MIPS_HFLAG_64) { 319*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_COP1X; 320*26aa3d9aSPhilippe Mathieu-Daudé } 321*26aa3d9aSPhilippe Mathieu-Daudé } else if (env->insn_flags & ISA_MIPS4) { 322*26aa3d9aSPhilippe Mathieu-Daudé /* All supported MIPS IV CPUs use the XX (CU3) to enable 323*26aa3d9aSPhilippe Mathieu-Daudé and disable the MIPS IV extensions to the MIPS III ISA. 324*26aa3d9aSPhilippe Mathieu-Daudé Some other MIPS IV CPUs ignore the bit, so the check here 325*26aa3d9aSPhilippe Mathieu-Daudé would be too restrictive for them. */ 326*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Status & (1U << CP0St_CU3)) { 327*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_COP1X; 328*26aa3d9aSPhilippe Mathieu-Daudé } 329*26aa3d9aSPhilippe Mathieu-Daudé } 330*26aa3d9aSPhilippe Mathieu-Daudé if (env->insn_flags & ASE_MSA) { 331*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Config5 & (1 << CP0C5_MSAEn)) { 332*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_MSA; 333*26aa3d9aSPhilippe Mathieu-Daudé } 334*26aa3d9aSPhilippe Mathieu-Daudé } 335*26aa3d9aSPhilippe Mathieu-Daudé if (env->active_fpu.fcr0 & (1 << FCR0_FREP)) { 336*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Config5 & (1 << CP0C5_FRE)) { 337*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_FRE; 338*26aa3d9aSPhilippe Mathieu-Daudé } 339*26aa3d9aSPhilippe Mathieu-Daudé } 340*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_Config3 & (1 << CP0C3_LPA)) { 341*26aa3d9aSPhilippe Mathieu-Daudé if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) { 342*26aa3d9aSPhilippe Mathieu-Daudé env->hflags |= MIPS_HFLAG_ELPA; 343*26aa3d9aSPhilippe Mathieu-Daudé } 344*26aa3d9aSPhilippe Mathieu-Daudé } 345*26aa3d9aSPhilippe Mathieu-Daudé } 346*26aa3d9aSPhilippe Mathieu-Daudé 347*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_tlb_flush(CPUMIPSState *env); 348*26aa3d9aSPhilippe Mathieu-Daudé void sync_c0_status(CPUMIPSState *env, CPUMIPSState *cpu, int tc); 349*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_store_status(CPUMIPSState *env, target_ulong val); 350*26aa3d9aSPhilippe Mathieu-Daudé void cpu_mips_store_cause(CPUMIPSState *env, target_ulong val); 351*26aa3d9aSPhilippe Mathieu-Daudé 352*26aa3d9aSPhilippe Mathieu-Daudé void QEMU_NORETURN do_raise_exception_err(CPUMIPSState *env, uint32_t exception, 353*26aa3d9aSPhilippe Mathieu-Daudé int error_code, uintptr_t pc); 354*26aa3d9aSPhilippe Mathieu-Daudé 355*26aa3d9aSPhilippe Mathieu-Daudé static inline void QEMU_NORETURN do_raise_exception(CPUMIPSState *env, 356*26aa3d9aSPhilippe Mathieu-Daudé uint32_t exception, 357*26aa3d9aSPhilippe Mathieu-Daudé uintptr_t pc) 358*26aa3d9aSPhilippe Mathieu-Daudé { 359*26aa3d9aSPhilippe Mathieu-Daudé do_raise_exception_err(env, exception, 0, pc); 360*26aa3d9aSPhilippe Mathieu-Daudé } 361*26aa3d9aSPhilippe Mathieu-Daudé 362*26aa3d9aSPhilippe Mathieu-Daudé #endif 363