diff --git a/qemu/target/mips/cpu.h b/qemu/target/mips/cpu.h index f63519b9..eeaa64bb 100644 --- a/qemu/target/mips/cpu.h +++ b/qemu/target/mips/cpu.h @@ -400,7 +400,9 @@ struct CPUMIPSState { #define CP0Ca_EC 2 target_ulong CP0_EPC; int32_t CP0_PRid; - int32_t CP0_EBase; + target_ulong CP0_EBase; + target_ulong CP0_EBaseWG_rw_bitmask; +#define CP0EBase_WG 11 target_ulong CP0_CMGCRBase; int32_t CP0_Config0; #define CP0C0_M 31 @@ -448,6 +450,7 @@ struct CPUMIPSState { #define CP0C3_MSAP 28 #define CP0C3_BP 27 #define CP0C3_BI 26 +#define CP0C3_SC 25 #define CP0C3_IPLW 21 #define CP0C3_MMAR 18 #define CP0C3_MCU 17 diff --git a/qemu/target/mips/helper.c b/qemu/target/mips/helper.c index f4e422b0..ac5e68d3 100644 --- a/qemu/target/mips/helper.c +++ b/qemu/target/mips/helper.c @@ -821,11 +821,7 @@ void mips_cpu_do_interrupt(CPUState *cs) goto set_EPC; case EXCP_CACHE: cause = 30; - if (env->CP0_Status & (1 << CP0St_BEV)) { - offset = 0x100; - } else { - offset = 0x20000100; - } + offset = 0x100; set_EPC: if (!(env->CP0_Status & (1 << CP0St_EXL))) { env->CP0_EPC = exception_resume_pc(env); @@ -851,9 +847,15 @@ void mips_cpu_do_interrupt(CPUState *cs) env->hflags &= ~MIPS_HFLAG_BMASK; if (env->CP0_Status & (1 << CP0St_BEV)) { env->active_tc.PC = env->exception_base + 0x200; + } else if (cause == 30 && !(env->CP0_Config3 & (1 << CP0C3_SC) && + env->CP0_Config5 & (1 << CP0C5_CV))) { + /* Force KSeg1 for cache errors */ + env->active_tc.PC = (int32_t)KSEG1_BASE | + (env->CP0_EBase & 0x1FFFF000); } else { - env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff); + env->active_tc.PC = env->CP0_EBase & ~0xfff; } + env->active_tc.PC += offset; set_hflags_for_handler(env); env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC); diff --git a/qemu/target/mips/op_helper.c b/qemu/target/mips/op_helper.c index 48c83464..7b75779c 100644 --- a/qemu/target/mips/op_helper.c +++ b/qemu/target/mips/op_helper.c @@ -1505,14 +1505,22 @@ target_ulong helper_mftc0_ebase(CPUMIPSState *env) void helper_mtc0_ebase(CPUMIPSState *env, target_ulong arg1) { - env->CP0_EBase = (env->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); + target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask; + if (arg1 & env->CP0_EBaseWG_rw_bitmask) { + mask |= ~0x3FFFFFFF; + } + env->CP0_EBase = (env->CP0_EBase & ~mask) | (arg1 & mask); } void helper_mttc0_ebase(CPUMIPSState *env, target_ulong arg1) { int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC); CPUMIPSState *other = mips_cpu_map_tc(env, &other_tc); - other->CP0_EBase = (other->CP0_EBase & ~0x3FFFF000) | (arg1 & 0x3FFFF000); + target_ulong mask = 0x3FFFF000 | env->CP0_EBaseWG_rw_bitmask; + if (arg1 & env->CP0_EBaseWG_rw_bitmask) { + mask |= ~0x3FFFFFFF; + } + other->CP0_EBase = (other->CP0_EBase & ~mask) | (arg1 & mask); } target_ulong helper_mftc0_configx(CPUMIPSState *env, target_ulong idx) diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index ee471ff3..01494681 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -5408,7 +5408,8 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) break; case 1: check_insn(ctx, ISA_MIPS32R2); - gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_EBase)); + tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_EBase)); + tcg_gen_ext32s_tl(tcg_ctx, arg, arg); rn = "EBase"; break; case 3: @@ -6714,7 +6715,7 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) break; case 1: check_insn(ctx, ISA_MIPS32R2); - gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_EBase)); + tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_EBase)); rn = "EBase"; break; default: @@ -20439,6 +20440,7 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4; env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask; env->CP0_PageGrain = env->cpu_model->CP0_PageGrain; + env->CP0_EBaseWG_rw_bitmask = env->cpu_model->CP0_EBaseWG_rw_bitmask; env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0; env->active_fpu.fcr31_rw_bitmask = env->cpu_model->CP1_fcr31_rw_bitmask; env->active_fpu.fcr31 = env->cpu_model->CP1_fcr31; @@ -20486,7 +20488,7 @@ void cpu_state_reset(CPUMIPSState *env) env->CP0_Wired = 0; env->CP0_GlobalNumber = (cs->cpu_index & 0xFF) << CP0GN_VPId; env->CP0_EBase = (cs->cpu_index & 0x3FF); - env->CP0_EBase |= 0x80000000; + env->CP0_EBase |= (int32_t)0x80000000; if (env->CP0_Config3 & (1 << CP0C3_CMGCR)) { env->CP0_CMGCRBase = 0x1fbf8000 >> 4; } diff --git a/qemu/target/mips/translate_init.c b/qemu/target/mips/translate_init.c index 94ca3b59..5b7d76d5 100644 --- a/qemu/target/mips/translate_init.c +++ b/qemu/target/mips/translate_init.c @@ -101,6 +101,7 @@ struct mips_def_t { int32_t CP0_SRSConf4; int32_t CP0_PageGrain_rw_bitmask; int32_t CP0_PageGrain; + target_ulong CP0_EBaseWG_rw_bitmask; int insn_flags; enum mips_mmu_types mmu_type; }; @@ -137,6 +138,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32, MMU_TYPE_R4000, }, @@ -172,6 +174,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32 | ASE_MIPS16, MMU_TYPE_FMT, }, @@ -203,6 +206,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32, MMU_TYPE_R4000, }, @@ -234,6 +238,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32 | ASE_MIPS16, MMU_TYPE_FMT, }, @@ -266,6 +271,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2, MMU_TYPE_R4000, }, @@ -298,6 +304,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MIPS16, MMU_TYPE_FMT, }, @@ -331,6 +338,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MIPS16, MMU_TYPE_R4000, }, @@ -369,6 +377,7 @@ static const mips_def_t mips_defs[] = 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP, MMU_TYPE_R4000, }, @@ -403,6 +412,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MIPS16, MMU_TYPE_R4000, }, @@ -453,6 +463,7 @@ static const mips_def_t mips_defs[] = (0x3fe << CP0SRSC4_SRS15) | (0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13), 0,0, + 0, CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_MT, MMU_TYPE_R4000, }, @@ -487,6 +498,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP | ASE_DSPR2, MMU_TYPE_R4000, }, @@ -518,6 +530,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MICROMIPS, MMU_TYPE_FMT, }, @@ -550,6 +563,7 @@ static const mips_def_t mips_defs[] = 32, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS32R2 | ASE_MICROMIPS, MMU_TYPE_R4000, }, @@ -599,6 +613,7 @@ static const mips_def_t mips_defs[] = 0,0, 0,0, 0,0, 0,0, 0,0, (1U << CP0PG_RIE) | (1 << CP0PG_XIE) | (1 << CP0PG_ELPA) | (1 << CP0PG_IEC), 0, + 0, CPU_MIPS32R5 | ASE_MSA, MMU_TYPE_R4000, }, @@ -646,6 +661,7 @@ static const mips_def_t mips_defs[] = 0,0, 0, (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | (1U << CP0PG_RIE), + 0, CPU_MIPS32R6 | ASE_MICROMIPS, MMU_TYPE_R4000, }, @@ -678,6 +694,7 @@ static const mips_def_t mips_defs[] = 40, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS3, MMU_TYPE_R4000, }, @@ -708,6 +725,7 @@ static const mips_def_t mips_defs[] = 40, 32, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_VR54XX, MMU_TYPE_R4000, }, @@ -740,6 +758,7 @@ static const mips_def_t mips_defs[] = 42, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64, MMU_TYPE_R4000, }, @@ -775,6 +794,7 @@ static const mips_def_t mips_defs[] = 42, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64, MMU_TYPE_R4000, }, @@ -812,6 +832,7 @@ static const mips_def_t mips_defs[] = 40, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64 | ASE_MIPS3D, MMU_TYPE_R4000, }, @@ -848,6 +869,7 @@ static const mips_def_t mips_defs[] = 42, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64R2 | ASE_MIPS3D, MMU_TYPE_R4000, }, @@ -892,6 +914,7 @@ static const mips_def_t mips_defs[] = (1 << CP0PG_ELPA), (1 << CP0PG_IEC) | (1 << CP0PG_XIE) | (1U << CP0PG_RIE), + 0, CPU_MIPS64R6 | ASE_MSA, MMU_TYPE_R4000, }, @@ -926,6 +949,7 @@ static const mips_def_t mips_defs[] = 42, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64R2, MMU_TYPE_R4000, }, @@ -962,6 +986,7 @@ static const mips_def_t mips_defs[] = 42, 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64R2, MMU_TYPE_R4000, }, @@ -993,6 +1018,7 @@ static const mips_def_t mips_defs[] = 40, 40, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_LOONGSON2E, MMU_TYPE_R4000, }, @@ -1024,6 +1050,7 @@ static const mips_def_t mips_defs[] = 40, 40, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_LOONGSON2F, MMU_TYPE_R4000, }, @@ -1064,6 +1091,7 @@ static const mips_def_t mips_defs[] = 59, */ /* the architectural limit */ 36, 0,0, 0,0, 0,0, 0,0, 0,0, 0,0, + 0, CPU_MIPS64R2 | ASE_DSP | ASE_DSPR2, MMU_TYPE_R4000, },