diff --git a/qemu/target/mips/cpu.h b/qemu/target/mips/cpu.h index 0a63a995..8c2aaeb3 100644 --- a/qemu/target/mips/cpu.h +++ b/qemu/target/mips/cpu.h @@ -417,6 +417,7 @@ struct CPUMIPSState { #define CP0SC2_XR 56 #define CP0SC2_XR_MASK (0xFFULL << CP0SC2_XR) #define CP0SC2_MASK (CP0SC_1GMASK | (CP0SC_1GMASK << 16) | CP0SC2_XR_MASK) + target_ulong CP0_PWBase; /* * CP0 Register 6 */ diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index 7a5978fd..f0a5da30 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -2486,6 +2486,20 @@ static inline void check_xnp(DisasContext *ctx) } } +#ifndef CONFIG_USER_ONLY +/* + * This code generates a "reserved instruction" exception if the + * Config3 PW bit is NOT set. + */ +static inline void check_pw(DisasContext *ctx) +{ + if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) { + generate_exception_end(ctx, EXCP_RI); + } +} +#endif + + /* * This code generates a "reserved instruction" exception if the * Config3 MT bit is NOT set. @@ -6176,6 +6190,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2)); tcg_gen_ext32s_tl(tcg_ctx, arg, arg); rn = "SegCtl2"; + case 5: + check_pw(ctx); + gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_PWBase)); + rn = "PWBase"; + break; break; default: goto cp0_unimplemented; @@ -6874,6 +6893,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_segctl2(tcg_ctx, tcg_ctx->cpu_env, arg); rn = "SegCtl2"; break; + case 5: + check_pw(ctx); + gen_mtc0_store32(ctx, arg, offsetof(CPUMIPSState, CP0_PWBase)); + rn = "PWBase"; + break; default: goto cp0_unimplemented; } @@ -7581,6 +7605,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2)); rn = "SegCtl2"; break; + case 5: + check_pw(ctx); + tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_PWBase)); + rn = "PWBase"; + break; default: goto cp0_unimplemented; } @@ -8260,6 +8289,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_helper_mtc0_segctl2(tcg_ctx, tcg_ctx->cpu_env, arg); rn = "SegCtl2"; break; + case 5: + check_pw(ctx); + tcg_gen_st_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_PWBase)); + rn = "PWBase"; + break; default: goto cp0_unimplemented; }