mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-10 21:45:37 +00:00
target/mips: Add an MMU mode for ERL
The segmentation control feature allows a legacy memory segment to become unmapped uncached at error level (according to CP0_Status.ERL), and in fact the user segment is already treated in this way by QEMU. Add a new MMU mode for this state so that QEMU's mappings don't persist between ERL=0 and ERL=1. Backports commit 42c86612d507c2a8789f2b8d920a244693c4ef7b from qemu
This commit is contained in:
parent
f285157856
commit
7e9b84ca1a
|
@ -135,7 +135,7 @@ struct CPUMIPSFPUContext {
|
||||||
#define FP_UNIMPLEMENTED 32
|
#define FP_UNIMPLEMENTED 32
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NB_MMU_MODES 3
|
#define NB_MMU_MODES 4
|
||||||
#define TARGET_INSN_START_EXTRA_WORDS 2
|
#define TARGET_INSN_START_EXTRA_WORDS 2
|
||||||
|
|
||||||
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
|
typedef struct CPUMIPSMVPContext CPUMIPSMVPContext;
|
||||||
|
@ -552,7 +552,7 @@ struct CPUMIPSState {
|
||||||
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
|
#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */
|
||||||
uint32_t hflags; /* CPU State */
|
uint32_t hflags; /* CPU State */
|
||||||
/* TMASK defines different execution modes */
|
/* TMASK defines different execution modes */
|
||||||
#define MIPS_HFLAG_TMASK 0xF5807FF
|
#define MIPS_HFLAG_TMASK 0x1F5807FF
|
||||||
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
|
#define MIPS_HFLAG_MODE 0x00007 /* execution modes */
|
||||||
/* The KSU flags must be the lowest bits in hflags. The flag order
|
/* 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
|
must be the same as defined for CP0 Status. This allows to use
|
||||||
|
@ -602,6 +602,7 @@ struct CPUMIPSState {
|
||||||
#define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */
|
#define MIPS_HFLAG_FRE 0x2000000 /* FRE enabled */
|
||||||
#define MIPS_HFLAG_ELPA 0x4000000
|
#define MIPS_HFLAG_ELPA 0x4000000
|
||||||
#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */
|
#define MIPS_HFLAG_ITC_CACHE 0x8000000 /* CACHE instr. operates on ITC tag */
|
||||||
|
#define MIPS_HFLAG_ERL 0x10000000 /* error level flag */
|
||||||
target_ulong btarget; /* Jump / branch target */
|
target_ulong btarget; /* Jump / branch target */
|
||||||
target_ulong bcond; /* Branch condition (if needed) */
|
target_ulong bcond; /* Branch condition (if needed) */
|
||||||
|
|
||||||
|
@ -697,11 +698,16 @@ extern uint32_t cpu_rddsp(uint32_t mask_num, CPUMIPSState *env);
|
||||||
#define MMU_MODE0_SUFFIX _kernel
|
#define MMU_MODE0_SUFFIX _kernel
|
||||||
#define MMU_MODE1_SUFFIX _super
|
#define MMU_MODE1_SUFFIX _super
|
||||||
#define MMU_MODE2_SUFFIX _user
|
#define MMU_MODE2_SUFFIX _user
|
||||||
|
#define MMU_MODE3_SUFFIX _error
|
||||||
#define MMU_USER_IDX 2
|
#define MMU_USER_IDX 2
|
||||||
|
|
||||||
static inline int hflags_mmu_index(uint32_t hflags)
|
static inline int hflags_mmu_index(uint32_t hflags)
|
||||||
{
|
{
|
||||||
return hflags & MIPS_HFLAG_KSU;
|
if (hflags & MIPS_HFLAG_ERL) {
|
||||||
|
return 3; /* ERL */
|
||||||
|
} else {
|
||||||
|
return hflags & MIPS_HFLAG_KSU;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
|
static inline int cpu_mmu_index (CPUMIPSState *env, bool ifetch)
|
||||||
|
@ -971,8 +977,10 @@ static inline void compute_hflags(CPUMIPSState *env)
|
||||||
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
|
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU |
|
||||||
MIPS_HFLAG_AWRAP | MIPS_HFLAG_DSP | MIPS_HFLAG_DSPR2 |
|
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);
|
MIPS_HFLAG_ELPA | MIPS_HFLAG_ERL);
|
||||||
|
if (env->CP0_Status & (1 << CP0St_ERL)) {
|
||||||
|
env->hflags |= MIPS_HFLAG_ERL;
|
||||||
|
}
|
||||||
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||||
!(env->hflags & MIPS_HFLAG_DM)) {
|
!(env->hflags & MIPS_HFLAG_DM)) {
|
||||||
|
|
|
@ -65,6 +65,7 @@ static inline type do_##name(CPUMIPSState *env, target_ulong addr, \
|
||||||
case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \
|
case 1: return (type) cpu_##insn##_super_ra(env, addr, retaddr); \
|
||||||
default: \
|
default: \
|
||||||
case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \
|
case 2: return (type) cpu_##insn##_user_ra(env, addr, retaddr); \
|
||||||
|
case 3: return (type) cpu_##insn##_error_ra(env, addr, retaddr); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,6 +93,9 @@ static inline void do_##name(CPUMIPSState *env, target_ulong addr, \
|
||||||
case 1: cpu_##insn##_super_ra(env, addr, val, retaddr); break; \
|
case 1: cpu_##insn##_super_ra(env, addr, val, retaddr); break; \
|
||||||
default: \
|
default: \
|
||||||
case 2: cpu_##insn##_user_ra(env, addr, val, retaddr); break; \
|
case 2: cpu_##insn##_user_ra(env, addr, val, retaddr); break; \
|
||||||
|
case 3: \
|
||||||
|
cpu_##insn##_error_ra(env, addr, val, retaddr); \
|
||||||
|
break; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1443,6 +1447,9 @@ void helper_mtc0_status(CPUMIPSState *env, target_ulong arg1)
|
||||||
val, val & env->CP0_Cause & CP0Ca_IP_mask,
|
val, val & env->CP0_Cause & CP0Ca_IP_mask,
|
||||||
env->CP0_Cause);
|
env->CP0_Cause);
|
||||||
switch (cpu_mmu_index(env, false)) {
|
switch (cpu_mmu_index(env, false)) {
|
||||||
|
case 3:
|
||||||
|
qemu_log(", ERL\n");
|
||||||
|
break;
|
||||||
case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
|
case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
|
||||||
case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
|
case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
|
||||||
case MIPS_HFLAG_KM: qemu_log("\n"); break;
|
case MIPS_HFLAG_KM: qemu_log("\n"); break;
|
||||||
|
@ -2245,6 +2252,9 @@ static void debug_post_eret(CPUMIPSState *env)
|
||||||
if (env->hflags & MIPS_HFLAG_DM)
|
if (env->hflags & MIPS_HFLAG_DM)
|
||||||
qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
|
qemu_log(" DEPC " TARGET_FMT_lx, env->CP0_DEPC);
|
||||||
switch (cpu_mmu_index(env, false)) {
|
switch (cpu_mmu_index(env, false)) {
|
||||||
|
case 3:
|
||||||
|
qemu_log(", ERL\n");
|
||||||
|
break;
|
||||||
case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
|
case MIPS_HFLAG_UM: qemu_log(", UM\n"); break;
|
||||||
case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
|
case MIPS_HFLAG_SM: qemu_log(", SM\n"); break;
|
||||||
case MIPS_HFLAG_KM: qemu_log("\n"); break;
|
case MIPS_HFLAG_KM: qemu_log("\n"); break;
|
||||||
|
|
Loading…
Reference in a new issue