@@ -290,6 +290,12 @@ struct CPUMIPSState {
#define CP0SC2_XR_MASK (0xFFULL << CP0SC2_XR)
#define CP0SC2_MASK (CP0SC_1GMASK | (CP0SC_1GMASK << 16) | CP0SC2_XR_MASK)
target_ulong CP0_PWBase;
+ target_ulong CP0_PWField;
+#define CP0PF_GDI 24 /* 29..24 */
+#define CP0PF_UDI 18 /* 23..18 */
+#define CP0PF_MDI 12 /* 17..12 */
+#define CP0PF_PTI 6 /* 11..6 */
+#define CP0PF_PTEI 0 /* 5..0 */
int32_t CP0_Wired;
int32_t CP0_SRSConf0_rw_bitmask;
int32_t CP0_SRSConf0;
@@ -120,6 +120,7 @@ DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
DEF_HELPER_2(mtc0_segctl0, void, env, tl)
DEF_HELPER_2(mtc0_segctl1, void, env, tl)
DEF_HELPER_2(mtc0_segctl2, void, env, tl)
+DEF_HELPER_2(mtc0_pwfield, void, env, tl)
DEF_HELPER_2(mtc0_wired, void, env, tl)
DEF_HELPER_2(mtc0_srsconf0, void, env, tl)
DEF_HELPER_2(mtc0_srsconf1, void, env, tl)
@@ -212,8 +212,8 @@ const VMStateDescription vmstate_tlb = {
const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
- .version_id = 12,
- .minimum_version_id = 12,
+ .version_id = 13,
+ .minimum_version_id = 13,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {
/* Active TC */
@@ -257,6 +257,7 @@ const VMStateDescription vmstate_mips_cpu = {
VMSTATE_UINTTL(env.CP0_SegCtl1, MIPSCPU),
VMSTATE_UINTTL(env.CP0_SegCtl2, MIPSCPU),
VMSTATE_UINTTL(env.CP0_PWBase, MIPSCPU),
+ VMSTATE_UINTTL(env.CP0_PWField, MIPSCPU),
VMSTATE_INT32(env.CP0_Wired, MIPSCPU),
VMSTATE_INT32(env.CP0_SRSConf0, MIPSCPU),
VMSTATE_INT32(env.CP0_SRSConf1, MIPSCPU),
@@ -1445,6 +1445,40 @@ void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
tlb_flush(cs);
}
+void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1)
+{
+#ifdef TARGET_MIPS64
+ env->CP0_PWField = arg1 & 0x3F3FFFFFFFULL;
+#else
+ uint32_t mask = 0x3FFFFFFF;
+ uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3F;
+ uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3F;
+
+ if ((env->insn_flags & ISA_MIPS32R6)) {
+ if (((arg1 >> CP0PF_GDI) & 0x3F) < 12) {
+ mask &= ~(0x3F << CP0PF_GDI);
+ }
+ if (((arg1 >> CP0PF_UDI) & 0x3F) < 12) {
+ mask &= ~(0x3F << CP0PF_UDI);
+ }
+ if (((arg1 >> CP0PF_MDI) & 0x3F) < 12) {
+ mask &= ~(0x3F << CP0PF_MDI);
+ }
+ if (((arg1 >> CP0PF_PTI) & 0x3F) < 12) {
+ mask &= ~(0x3F << CP0PF_PTI);
+ }
+ }
+ env->CP0_PWField = arg1 & mask;
+
+ if ((new_ptei >= 32) ||
+ ((env->insn_flags & ISA_MIPS32R6) &&
+ (new_ptei == 0 || new_ptei == 1))) {
+ env->CP0_PWField = (env->CP0_PWField & ~0x3F) |
+ (old_ptei << CP0PF_PTEI);
+ }
+#endif
+}
+
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
{
if (env->insn_flags & ISA_MIPS32R6) {
@@ -5553,6 +5553,11 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
rn = "PWBase";
break;
+ case 6:
+ check_pw(ctx);
+ gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
+ rn = "PWField";
+ break;
default:
goto cp0_unimplemented;
}
@@ -6259,6 +6264,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
rn = "PWBase";
break;
+ case 6:
+ check_pw(ctx);
+ gen_helper_mtc0_pwfield(cpu_env, arg);
+ rn = "PWField";
+ break;
default:
goto cp0_unimplemented;
}
@@ -6974,6 +6984,11 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
rn = "PWBase";
break;
+ case 6:
+ check_pw(ctx);
+ tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
+ rn = "PWField";
+ break;
default:
goto cp0_unimplemented;
}
@@ -7662,6 +7677,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
rn = "PWBase";
break;
+ case 6:
+ check_pw(ctx);
+ gen_helper_mtc0_pwfield(cpu_env, arg);
+ rn = "PWField";
+ break;
default:
goto cp0_unimplemented;
}