mirror of https://github.com/xqemu/xqemu.git
target-mips: add CP0.PageGrain.ELPA support
CP0.PageGrain.ELPA enables support for large physical addresses. This field is encoded as follows: 0: Large physical address support is disabled. 1: Large physical address support is enabled. If this bit is a 1, the following changes occur to coprocessor 0 registers: - The PFNX field of the EntryLo0 and EntryLo1 registers is writable and concatenated with the PFN field to form the full page frame number. - Access to optional COP0 registers with PA extension, LLAddr, TagLo is defined. P5600 can operate in 32-bit or 40-bit Physical Address Mode. Therefore if XPA is disabled (CP0.PageGrain.ELPA = 0) then assume 32-bit Address Mode. In MIPS64 assume 36 as default PABITS (when CP0.PageGrain.ELPA = 0). env->PABITS value is constant and indicates maximum PABITS available on a core, whereas env->PAMask is calculated from env->PABITS and is also affected by CP0.PageGrain.ELPA. Signed-off-by: Leon Alrae <leon.alrae@imgtec.com> Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
parent
cd0d45c401
commit
e117f52636
|
@ -224,8 +224,14 @@ struct CPUMIPSState {
|
|||
|
||||
uint32_t SEGBITS;
|
||||
uint32_t PABITS;
|
||||
#if defined(TARGET_MIPS64)
|
||||
# define PABITS_BASE 36
|
||||
#else
|
||||
# define PABITS_BASE 32
|
||||
#endif
|
||||
target_ulong SEGMask;
|
||||
uint64_t PAMask;
|
||||
#define PAMASK_BASE ((1ULL << PABITS_BASE) - 1)
|
||||
|
||||
int32_t msair;
|
||||
#define MSAIR_ProcID 8
|
||||
|
@ -289,6 +295,7 @@ struct CPUMIPSState {
|
|||
int32_t CP0_PageGrain;
|
||||
#define CP0PG_RIE 31
|
||||
#define CP0PG_XIE 30
|
||||
#define CP0PG_ELPA 29
|
||||
#define CP0PG_IEC 27
|
||||
int32_t CP0_Wired;
|
||||
int32_t CP0_SRSConf0_rw_bitmask;
|
||||
|
@ -518,7 +525,7 @@ struct CPUMIPSState {
|
|||
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
|
||||
uint32_t hflags; /* CPU State */
|
||||
/* TMASK defines different execution modes */
|
||||
#define MIPS_HFLAG_TMASK 0x35807FF
|
||||
#define MIPS_HFLAG_TMASK 0x75807FF
|
||||
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
|
||||
/* The KSU flags must be the lowest bits in hflags. The flag order
|
||||
must be the same as defined for CP0 Status. This allows to use
|
||||
|
@ -566,6 +573,7 @@ struct CPUMIPSState {
|
|||
#define MIPS_HFLAG_FBNSLOT 0x800000 /* Forbidden slot */
|
||||
#define MIPS_HFLAG_MSA 0x1000000
|
||||
#define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */
|
||||
#define MIPS_HFLAG_ELPA 0x4000000
|
||||
target_ulong btarget; /* Jump / branch target */
|
||||
target_ulong bcond; /* Branch condition (if needed) */
|
||||
|
||||
|
@ -801,6 +809,15 @@ static inline void restore_msa_fp_status(CPUMIPSState *env)
|
|||
set_flush_inputs_to_zero(flush_to_zero, status);
|
||||
}
|
||||
|
||||
static inline void restore_pamask(CPUMIPSState *env)
|
||||
{
|
||||
if (env->hflags & MIPS_HFLAG_ELPA) {
|
||||
env->PAMask = (1ULL << env->PABITS) - 1;
|
||||
} else {
|
||||
env->PAMask = PAMASK_BASE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_get_tb_cpu_state(CPUMIPSState *env, target_ulong *pc,
|
||||
target_ulong *cs_base, int *flags)
|
||||
{
|
||||
|
@ -848,7 +865,8 @@ static inline void compute_hflags(CPUMIPSState *env)
|
|||
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
|
||||
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
|
||||
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
|
||||
MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE);
|
||||
MIPS_HFLAG_SBRI | MIPS_HFLAG_MSA | MIPS_HFLAG_FRE |
|
||||
MIPS_HFLAG_ELPA);
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||
!(env->hflags & MIPS_HFLAG_DM)) {
|
||||
|
@ -934,6 +952,11 @@ static inline void compute_hflags(CPUMIPSState *env)
|
|||
env->hflags |= MIPS_HFLAG_FRE;
|
||||
}
|
||||
}
|
||||
if (env->CP0_Config3 & (1 << CP0C3_LPA)) {
|
||||
if (env->CP0_PageGrain & (1 << CP0PG_ELPA)) {
|
||||
env->hflags |= MIPS_HFLAG_ELPA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
|
|
@ -10,6 +10,7 @@ static int cpu_post_load(void *opaque, int version_id)
|
|||
restore_fp_status(env);
|
||||
restore_msa_fp_status(env);
|
||||
compute_hflags(env);
|
||||
restore_pamask(env);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define TARGET_LONG_BITS 64
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 48
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 42
|
||||
#else
|
||||
#define TARGET_LONG_BITS 32
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 36
|
||||
#define TARGET_PHYS_ADDR_SPACE_BITS 40
|
||||
#define TARGET_VIRT_ADDR_SPACE_BITS 32
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1068,19 +1068,23 @@ void helper_mtc0_vpeopt(CPUMIPSState *env, target_ulong arg1)
|
|||
env->CP0_VPEOpt = arg1 & 0x0000ffff;
|
||||
}
|
||||
|
||||
#define MTC0_ENTRYLO_MASK(env) ((env->PAMask >> 6) & 0x3FFFFFFF)
|
||||
|
||||
void helper_mtc0_entrylo0(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
/* Large physaddr (PABITS) not implemented */
|
||||
/* 1k pages not implemented */
|
||||
target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
|
||||
env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
|
||||
env->CP0_EntryLo0 = (arg1 & MTC0_ENTRYLO_MASK(env))
|
||||
| (rxi << (CP0EnLo_XI - 30));
|
||||
}
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
#define DMTC0_ENTRYLO_MASK(env) (env->PAMask >> 6)
|
||||
|
||||
void helper_dmtc0_entrylo0(CPUMIPSState *env, uint64_t arg1)
|
||||
{
|
||||
uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
|
||||
env->CP0_EntryLo0 = (arg1 & 0x3FFFFFFF) | rxi;
|
||||
env->CP0_EntryLo0 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1246,17 +1250,17 @@ void helper_mttc0_tcschefback(CPUMIPSState *env, target_ulong arg1)
|
|||
|
||||
void helper_mtc0_entrylo1(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
/* Large physaddr (PABITS) not implemented */
|
||||
/* 1k pages not implemented */
|
||||
target_ulong rxi = arg1 & (env->CP0_PageGrain & (3u << CP0PG_XIE));
|
||||
env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | (rxi << (CP0EnLo_XI - 30));
|
||||
env->CP0_EntryLo1 = (arg1 & MTC0_ENTRYLO_MASK(env))
|
||||
| (rxi << (CP0EnLo_XI - 30));
|
||||
}
|
||||
|
||||
#if defined(TARGET_MIPS64)
|
||||
void helper_dmtc0_entrylo1(CPUMIPSState *env, uint64_t arg1)
|
||||
{
|
||||
uint64_t rxi = arg1 & ((env->CP0_PageGrain & (3ull << CP0PG_XIE)) << 32);
|
||||
env->CP0_EntryLo1 = (arg1 & 0x3FFFFFFF) | rxi;
|
||||
env->CP0_EntryLo1 = (arg1 & DMTC0_ENTRYLO_MASK(env)) | rxi;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1279,10 +1283,11 @@ void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
|
|||
void helper_mtc0_pagegrain(CPUMIPSState *env, target_ulong arg1)
|
||||
{
|
||||
/* SmartMIPS not implemented */
|
||||
/* Large physaddr (PABITS) not implemented */
|
||||
/* 1k pages not implemented */
|
||||
env->CP0_PageGrain = (arg1 & env->CP0_PageGrain_rw_bitmask) |
|
||||
(env->CP0_PageGrain & ~env->CP0_PageGrain_rw_bitmask);
|
||||
compute_hflags(env);
|
||||
restore_pamask(env);
|
||||
}
|
||||
|
||||
void helper_mtc0_wired(CPUMIPSState *env, target_ulong arg1)
|
||||
|
|
|
@ -5699,6 +5699,7 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
|||
check_insn(ctx, ISA_MIPS32R2);
|
||||
gen_helper_mtc0_pagegrain(cpu_env, arg);
|
||||
rn = "PageGrain";
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
default:
|
||||
goto cp0_unimplemented;
|
||||
|
@ -19578,7 +19579,6 @@ void cpu_state_reset(CPUMIPSState *env)
|
|||
}
|
||||
#endif
|
||||
env->PABITS = env->cpu_model->PABITS;
|
||||
env->PAMask = (1ULL << env->cpu_model->PABITS) - 1;
|
||||
env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
|
||||
env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
|
||||
env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
|
||||
|
@ -19699,6 +19699,7 @@ void cpu_state_reset(CPUMIPSState *env)
|
|||
compute_hflags(env);
|
||||
restore_rounding_mode(env);
|
||||
restore_flush_mode(env);
|
||||
restore_pamask(env);
|
||||
cs->exception_index = EXCP_NONE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue