mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-10 23:45:33 +00:00
target/mips: Add segmentation control registers
The optional segmentation control registers CP0_SegCtl0, CP0_SegCtl1 & CP0_SegCtl2 control the behaviour and required privilege of the legacy virtual memory segments. Add them to the CP0 interface so they can be read and written when CP0_Config3.SC=1, and initialise them to describe the standard legacy layout so they can be used in future patches regardless of whether they are exposed to the guest. Backports commit cec56a733dd2c3fa81dbedbecf03922258747f7d from qemu
This commit is contained in:
parent
7e9b84ca1a
commit
ddbea9422c
|
@ -4138,6 +4138,9 @@ mips_symbols = (
|
|||
'helper_mtc0_pagegrain',
|
||||
'helper_mtc0_pagemask',
|
||||
'helper_mtc0_performance0',
|
||||
'helper_mtc0_segctl0',
|
||||
'helper_mtc0_segctl1',
|
||||
'helper_mtc0_segctl2',
|
||||
'helper_mtc0_srsconf0',
|
||||
'helper_mtc0_srsconf1',
|
||||
'helper_mtc0_srsconf2',
|
||||
|
|
|
@ -4074,6 +4074,9 @@
|
|||
#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_segctl0 helper_mtc0_segctl0_mips
|
||||
#define helper_mtc0_segctl1 helper_mtc0_segctl1_mips
|
||||
#define helper_mtc0_segctl2 helper_mtc0_segctl2_mips
|
||||
#define helper_mtc0_srsconf0 helper_mtc0_srsconf0_mips
|
||||
#define helper_mtc0_srsconf1 helper_mtc0_srsconf1_mips
|
||||
#define helper_mtc0_srsconf2 helper_mtc0_srsconf2_mips
|
||||
|
|
|
@ -4074,6 +4074,9 @@
|
|||
#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_segctl0 helper_mtc0_segctl0_mips64
|
||||
#define helper_mtc0_segctl1 helper_mtc0_segctl1_mips64
|
||||
#define helper_mtc0_segctl2 helper_mtc0_segctl2_mips64
|
||||
#define helper_mtc0_srsconf0 helper_mtc0_srsconf0_mips64
|
||||
#define helper_mtc0_srsconf1 helper_mtc0_srsconf1_mips64
|
||||
#define helper_mtc0_srsconf2 helper_mtc0_srsconf2_mips64
|
||||
|
|
|
@ -4074,6 +4074,9 @@
|
|||
#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_segctl0 helper_mtc0_segctl0_mips64el
|
||||
#define helper_mtc0_segctl1 helper_mtc0_segctl1_mips64el
|
||||
#define helper_mtc0_segctl2 helper_mtc0_segctl2_mips64el
|
||||
#define helper_mtc0_srsconf0 helper_mtc0_srsconf0_mips64el
|
||||
#define helper_mtc0_srsconf1 helper_mtc0_srsconf1_mips64el
|
||||
#define helper_mtc0_srsconf2 helper_mtc0_srsconf2_mips64el
|
||||
|
|
|
@ -4074,6 +4074,9 @@
|
|||
#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_segctl0 helper_mtc0_segctl0_mipsel
|
||||
#define helper_mtc0_segctl1 helper_mtc0_segctl1_mipsel
|
||||
#define helper_mtc0_segctl2 helper_mtc0_segctl2_mipsel
|
||||
#define helper_mtc0_srsconf0 helper_mtc0_srsconf0_mipsel
|
||||
#define helper_mtc0_srsconf1 helper_mtc0_srsconf1_mipsel
|
||||
#define helper_mtc0_srsconf2 helper_mtc0_srsconf2_mipsel
|
||||
|
|
|
@ -307,6 +307,36 @@ struct CPUMIPSState {
|
|||
#define CP0PG_XIE 30
|
||||
#define CP0PG_ELPA 29
|
||||
#define CP0PG_IEC 27
|
||||
target_ulong CP0_SegCtl0;
|
||||
target_ulong CP0_SegCtl1;
|
||||
target_ulong CP0_SegCtl2;
|
||||
#define CP0SC_PA 9
|
||||
#define CP0SC_PA_MASK (0x7FULL << CP0SC_PA)
|
||||
#define CP0SC_PA_1GMASK (0x7EULL << CP0SC_PA)
|
||||
#define CP0SC_AM 4
|
||||
#define CP0SC_AM_MASK (0x7ULL << CP0SC_AM)
|
||||
#define CP0SC_AM_UK 0ULL
|
||||
#define CP0SC_AM_MK 1ULL
|
||||
#define CP0SC_AM_MSK 2ULL
|
||||
#define CP0SC_AM_MUSK 3ULL
|
||||
#define CP0SC_AM_MUSUK 4ULL
|
||||
#define CP0SC_AM_USK 5ULL
|
||||
#define CP0SC_AM_UUSK 7ULL
|
||||
#define CP0SC_EU 3
|
||||
#define CP0SC_EU_MASK (1ULL << CP0SC_EU)
|
||||
#define CP0SC_C 0
|
||||
#define CP0SC_C_MASK (0x7ULL << CP0SC_C)
|
||||
#define CP0SC_MASK (CP0SC_C_MASK | CP0SC_EU_MASK | CP0SC_AM_MASK | \
|
||||
CP0SC_PA_MASK)
|
||||
#define CP0SC_1GMASK (CP0SC_C_MASK | CP0SC_EU_MASK | CP0SC_AM_MASK | \
|
||||
CP0SC_PA_1GMASK)
|
||||
#define CP0SC0_MASK (CP0SC_MASK | (CP0SC_MASK << 16))
|
||||
#define CP0SC1_XAM 59
|
||||
#define CP0SC1_XAM_MASK (0x7ULL << CP0SC1_XAM)
|
||||
#define CP0SC1_MASK (CP0SC_MASK | (CP0SC_MASK << 16) | CP0SC1_XAM_MASK)
|
||||
#define CP0SC2_XR 56
|
||||
#define CP0SC2_XR_MASK (0xFFULL << CP0SC2_XR)
|
||||
#define CP0SC2_MASK (CP0SC_1GMASK | (CP0SC_1GMASK << 16) | CP0SC2_XR_MASK)
|
||||
int32_t CP0_Wired;
|
||||
int32_t CP0_SRSConf0_rw_bitmask;
|
||||
int32_t CP0_SRSConf0;
|
||||
|
|
|
@ -115,6 +115,9 @@ DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
|
|||
DEF_HELPER_2(mtc0_context, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_pagemask, void, env, tl)
|
||||
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_wired, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf0, void, env, tl)
|
||||
DEF_HELPER_2(mtc0_srsconf1, void, env, tl)
|
||||
|
|
|
@ -1318,6 +1318,30 @@ void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
|
|||
restore_pamask(env);
|
||||
}
|
||||
|
||||
void helper_mtc0_segctl0(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
|
||||
env->CP0_SegCtl0 = arg1 & CP0SC0_MASK;
|
||||
tlb_flush(cs);
|
||||
}
|
||||
|
||||
void helper_mtc0_segctl1(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
|
||||
env->CP0_SegCtl1 = arg1 & CP0SC1_MASK;
|
||||
tlb_flush(cs);
|
||||
}
|
||||
|
||||
void helper_mtc0_segctl2(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
CPUState *cs = CPU(mips_env_get_cpu(env));
|
||||
|
||||
env->CP0_SegCtl2 = arg1 & CP0SC2_MASK;
|
||||
tlb_flush(cs);
|
||||
}
|
||||
|
||||
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
if (env->insn_flags & ISA_MIPS32R6) {
|
||||
|
|
|
@ -1434,6 +1434,7 @@ typedef struct DisasContext {
|
|||
uint64_t PAMask;
|
||||
bool mvh;
|
||||
bool eva;
|
||||
bool sc;
|
||||
int CP0_LLAddr_shift;
|
||||
bool ps;
|
||||
bool vp;
|
||||
|
@ -5309,7 +5310,24 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
check_insn(ctx, ISA_MIPS32R2);
|
||||
gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_PageGrain));
|
||||
rn = "PageGrain";
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case 2:
|
||||
CP0_CHECK(ctx->sc);
|
||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
|
||||
tcg_gen_ext32s_tl(tcg_ctx, arg, arg);
|
||||
rn = "SegCtl0";
|
||||
break;
|
||||
case 3:
|
||||
CP0_CHECK(ctx->sc);
|
||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
|
||||
tcg_gen_ext32s_tl(tcg_ctx, arg, arg);
|
||||
rn = "SegCtl1";
|
||||
break;
|
||||
case 4:
|
||||
CP0_CHECK(ctx->sc);
|
||||
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";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
|
@ -5965,6 +5983,22 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
check_insn(ctx, ISA_MIPS32R2);
|
||||
gen_helper_mtc0_pagegrain(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "PageGrain";
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case 2:
|
||||
CP0_CHECK(ctx->sc);
|
||||
gen_helper_mtc0_segctl0(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "SegCtl0";
|
||||
break;
|
||||
case 3:
|
||||
CP0_CHECK(ctx->sc);
|
||||
gen_helper_mtc0_segctl1(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "SegCtl1";
|
||||
break;
|
||||
case 4:
|
||||
CP0_CHECK(ctx->sc);
|
||||
gen_helper_mtc0_segctl2(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "SegCtl2";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
|
@ -6634,6 +6668,21 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
gen_mfc0_load32(ctx, arg, offsetof(CPUMIPSState, CP0_PageGrain));
|
||||
rn = "PageGrain";
|
||||
break;
|
||||
case 2:
|
||||
CP0_CHECK(ctx->sc);
|
||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
|
||||
rn = "SegCtl0";
|
||||
break;
|
||||
case 3:
|
||||
CP0_CHECK(ctx->sc);
|
||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
|
||||
rn = "SegCtl1";
|
||||
break;
|
||||
case 4:
|
||||
CP0_CHECK(ctx->sc);
|
||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
|
||||
rn = "SegCtl2";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
|
@ -7267,6 +7316,21 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
gen_helper_mtc0_pagegrain(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "PageGrain";
|
||||
break;
|
||||
case 2:
|
||||
CP0_CHECK(ctx->sc);
|
||||
gen_helper_mtc0_segctl0(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "SegCtl0";
|
||||
break;
|
||||
case 3:
|
||||
CP0_CHECK(ctx->sc);
|
||||
gen_helper_mtc0_segctl1(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "SegCtl1";
|
||||
break;
|
||||
case 4:
|
||||
CP0_CHECK(ctx->sc);
|
||||
gen_helper_mtc0_segctl2(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||
rn = "SegCtl2";
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
}
|
||||
|
@ -20322,6 +20386,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
|
|||
ctx.PAMask = env->PAMask;
|
||||
ctx.mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
|
||||
ctx.eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
|
||||
ctx.sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
|
||||
ctx.CP0_LLAddr_shift = env->CP0_LLAddr_shift;
|
||||
ctx.cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
|
||||
/* Restore delay slot state from the tb context. */
|
||||
|
@ -20813,6 +20878,29 @@ void cpu_state_reset(CPUMIPSState *env)
|
|||
env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Configure default legacy segmentation control. We use this regardless of
|
||||
* whether segmentation control is presented to the guest.
|
||||
*/
|
||||
/* KSeg3 (seg0 0xE0000000..0xFFFFFFFF) */
|
||||
env->CP0_SegCtl0 = (CP0SC_AM_MK << CP0SC_AM);
|
||||
/* KSeg2 (seg1 0xC0000000..0xDFFFFFFF) */
|
||||
env->CP0_SegCtl0 |= ((CP0SC_AM_MSK << CP0SC_AM)) << 16;
|
||||
/* KSeg1 (seg2 0xA0000000..0x9FFFFFFF) */
|
||||
env->CP0_SegCtl1 = (0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
|
||||
(2 << CP0SC_C);
|
||||
/* KSeg0 (seg3 0x80000000..0x9FFFFFFF) */
|
||||
env->CP0_SegCtl1 |= ((0 << CP0SC_PA) | (CP0SC_AM_UK << CP0SC_AM) |
|
||||
(3 << CP0SC_C)) << 16;
|
||||
/* USeg (seg4 0x40000000..0x7FFFFFFF) */
|
||||
env->CP0_SegCtl2 = (2 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
|
||||
(1 << CP0SC_EU) | (2 << CP0SC_C);
|
||||
/* USeg (seg5 0x00000000..0x3FFFFFFF) */
|
||||
env->CP0_SegCtl2 |= ((0 << CP0SC_PA) | (CP0SC_AM_MUSK << CP0SC_AM) |
|
||||
(1 << CP0SC_EU) | (2 << CP0SC_C)) << 16;
|
||||
/* XKPhys (note, SegCtl2.XR = 0, so XAM won't be used) */
|
||||
env->CP0_SegCtl1 |= (CP0SC_AM_UK << CP0SC1_XAM);
|
||||
#endif
|
||||
if ((env->insn_flags & ISA_MIPS32R6) &&
|
||||
(env->active_fpu.fcr0 & (1 << FCR0_F64))) {
|
||||
|
|
Loading…
Reference in a new issue