diff --git a/qemu/header_gen.py b/qemu/header_gen.py index 56e68be1..005dbf69 100644 --- a/qemu/header_gen.py +++ b/qemu/header_gen.py @@ -4934,6 +4934,7 @@ mips_symbols = ( 'helper_mtc0_pagegrain', 'helper_mtc0_pagemask', 'helper_mtc0_performance0', + 'helper_mtc0_pwfield', 'helper_mtc0_segctl0', 'helper_mtc0_segctl1', 'helper_mtc0_segctl2', diff --git a/qemu/mips.h b/qemu/mips.h index 52787ac3..f1409661 100644 --- a/qemu/mips.h +++ b/qemu/mips.h @@ -3908,6 +3908,7 @@ #define helper_mtc0_pagegrain helper_mtc0_pagegrain_mips #define helper_mtc0_pagemask helper_mtc0_pagemask_mips #define helper_mtc0_performance0 helper_mtc0_performance0_mips +#define helper_mtc0_pwfield helper_mtc0_pwfield_mips #define helper_mtc0_segctl0 helper_mtc0_segctl0_mips #define helper_mtc0_segctl1 helper_mtc0_segctl1_mips #define helper_mtc0_segctl2 helper_mtc0_segctl2_mips diff --git a/qemu/mips64.h b/qemu/mips64.h index 111340c5..ccd4718e 100644 --- a/qemu/mips64.h +++ b/qemu/mips64.h @@ -3908,6 +3908,7 @@ #define helper_mtc0_pagegrain helper_mtc0_pagegrain_mips64 #define helper_mtc0_pagemask helper_mtc0_pagemask_mips64 #define helper_mtc0_performance0 helper_mtc0_performance0_mips64 +#define helper_mtc0_pwfield helper_mtc0_pwfield_mips64 #define helper_mtc0_segctl0 helper_mtc0_segctl0_mips64 #define helper_mtc0_segctl1 helper_mtc0_segctl1_mips64 #define helper_mtc0_segctl2 helper_mtc0_segctl2_mips64 diff --git a/qemu/mips64el.h b/qemu/mips64el.h index e3e336fb..e769fefd 100644 --- a/qemu/mips64el.h +++ b/qemu/mips64el.h @@ -3908,6 +3908,7 @@ #define helper_mtc0_pagegrain helper_mtc0_pagegrain_mips64el #define helper_mtc0_pagemask helper_mtc0_pagemask_mips64el #define helper_mtc0_performance0 helper_mtc0_performance0_mips64el +#define helper_mtc0_pwfield helper_mtc0_pwfield_mips64el #define helper_mtc0_segctl0 helper_mtc0_segctl0_mips64el #define helper_mtc0_segctl1 helper_mtc0_segctl1_mips64el #define helper_mtc0_segctl2 helper_mtc0_segctl2_mips64el diff --git a/qemu/mipsel.h b/qemu/mipsel.h index 4e1e51ec..1359db5d 100644 --- a/qemu/mipsel.h +++ b/qemu/mipsel.h @@ -3908,6 +3908,7 @@ #define helper_mtc0_pagegrain helper_mtc0_pagegrain_mipsel #define helper_mtc0_pagemask helper_mtc0_pagemask_mipsel #define helper_mtc0_performance0 helper_mtc0_performance0_mipsel +#define helper_mtc0_pwfield helper_mtc0_pwfield_mipsel #define helper_mtc0_segctl0 helper_mtc0_segctl0_mipsel #define helper_mtc0_segctl1 helper_mtc0_segctl1_mipsel #define helper_mtc0_segctl2 helper_mtc0_segctl2_mipsel diff --git a/qemu/target/mips/cpu.h b/qemu/target/mips/cpu.h index 8c2aaeb3..2b66814c 100644 --- a/qemu/target/mips/cpu.h +++ b/qemu/target/mips/cpu.h @@ -418,6 +418,21 @@ 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; +#if defined(TARGET_MIPS64) +#define CP0PF_BDI 32 /* 37..32 */ +#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 */ +#else +#define CP0PF_GDW 24 /* 29..24 */ +#define CP0PF_UDW 18 /* 23..18 */ +#define CP0PF_MDW 12 /* 17..12 */ +#define CP0PF_PTW 6 /* 11..6 */ +#define CP0PF_PTEW 0 /* 5..0 */ +#endif /* * CP0 Register 6 */ diff --git a/qemu/target/mips/helper.h b/qemu/target/mips/helper.h index 404444ee..f906f0da 100644 --- a/qemu/target/mips/helper.h +++ b/qemu/target/mips/helper.h @@ -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) diff --git a/qemu/target/mips/op_helper.c b/qemu/target/mips/op_helper.c index 5b7bbfc4..6a09a0f3 100644 --- a/qemu/target/mips/op_helper.c +++ b/qemu/target/mips/op_helper.c @@ -1435,6 +1435,68 @@ void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1) tlb_flush(cs); } +void helper_mtc0_pwfield(CPUMIPSState *env, target_ulong arg1) +{ +#if defined(TARGET_MIPS64) + uint64_t mask = 0x3F3FFFFFFFULL; + uint32_t old_ptei = (env->CP0_PWField >> CP0PF_PTEI) & 0x3FULL; + uint32_t new_ptei = (arg1 >> CP0PF_PTEI) & 0x3FULL; + + if ((env->insn_flags & ISA_MIPS32R6)) { + if (((arg1 >> CP0PF_BDI) & 0x3FULL) < 12) { + mask &= ~(0x3FULL << CP0PF_BDI); + } + if (((arg1 >> CP0PF_GDI) & 0x3FULL) < 12) { + mask &= ~(0x3FULL << CP0PF_GDI); + } + if (((arg1 >> CP0PF_UDI) & 0x3FULL) < 12) { + mask &= ~(0x3FULL << CP0PF_UDI); + } + if (((arg1 >> CP0PF_MDI) & 0x3FULL) < 12) { + mask &= ~(0x3FULL << CP0PF_MDI); + } + if (((arg1 >> CP0PF_PTI) & 0x3FULL) < 12) { + mask &= ~(0x3FULL << 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 & ~0x3FULL) | + (old_ptei << CP0PF_PTEI); + } +#else + uint32_t mask = 0x3FFFFFFF; + uint32_t old_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; + uint32_t new_ptew = (arg1 >> CP0PF_PTEW) & 0x3F; + + if ((env->insn_flags & ISA_MIPS32R6)) { + if (((arg1 >> CP0PF_GDW) & 0x3F) < 12) { + mask &= ~(0x3F << CP0PF_GDW); + } + if (((arg1 >> CP0PF_UDW) & 0x3F) < 12) { + mask &= ~(0x3F << CP0PF_UDW); + } + if (((arg1 >> CP0PF_MDW) & 0x3F) < 12) { + mask &= ~(0x3F << CP0PF_MDW); + } + if (((arg1 >> CP0PF_PTW) & 0x3F) < 12) { + mask &= ~(0x3F << CP0PF_PTW); + } + } + env->CP0_PWField = arg1 & mask; + + if ((new_ptew >= 32) || + ((env->insn_flags & ISA_MIPS32R6) && + (new_ptew == 0 || new_ptew == 1))) { + env->CP0_PWField = (env->CP0_PWField & ~0x3F) | + (old_ptew << CP0PF_PTEW); + } +#endif +} + void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1) { if (env->insn_flags & ISA_MIPS32R6) { diff --git a/qemu/target/mips/translate.c b/qemu/target/mips/translate.c index f0a5da30..bcccfe10 100644 --- a/qemu/target/mips/translate.c +++ b/qemu/target/mips/translate.c @@ -6195,6 +6195,10 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_PWBase)); rn = "PWBase"; break; + case 6: + check_pw(ctx); + gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_PWField)); + rn = "PWField"; break; default: goto cp0_unimplemented; @@ -6898,6 +6902,11 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel) gen_mtc0_store32(ctx, arg, offsetof(CPUMIPSState, CP0_PWBase)); rn = "PWBase"; break; + case 6: + check_pw(ctx); + gen_helper_mtc0_pwfield(tcg_ctx, tcg_ctx->cpu_env, arg); + rn = "PWField"; + break; default: goto cp0_unimplemented; } @@ -7610,6 +7619,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_PWBase)); rn = "PWBase"; break; + case 6: + check_pw(ctx); + tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_PWField)); + rn = "PWField"; + break; default: goto cp0_unimplemented; } @@ -8294,6 +8308,11 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel) tcg_gen_st_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_PWBase)); rn = "PWBase"; break; + case 6: + check_pw(ctx); + gen_helper_mtc0_pwfield(tcg_ctx, tcg_ctx->cpu_env, arg); + rn = "PWField"; + break; default: goto cp0_unimplemented; }