When CRS = 0, we restore from estatus; otherwise from sstatus. Do not allow reserved status bits to be set via this restore. Add the fields defined for EIC to status.
Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- target/nios2/cpu.h | 1 + target/nios2/cpu.c | 16 ++++++++++++---- target/nios2/op_helper.c | 20 +++++++++++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index efaac274aa..c48daa5640 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -83,6 +83,7 @@ enum { R_FP = 28, R_EA = 29, R_BA = 30, + R_SSTATUS = 30, R_RA = 31, }; diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index 05f4a7a93a..6ece92a2b8 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -109,10 +109,18 @@ static void nios2_cpu_initfn(Object *obj) WR_FIELD(CR_EXCEPTION, CAUSE); WR_REG(CR_BADADDR); - /* TODO: These control registers are not present with the EIC. */ - RO_FIELD(CR_STATUS, RSIE); - WR_REG(CR_IENABLE); - RO_REG(CR_IPENDING); + if (cpu->eic_present) { + WR_FIELD(CR_STATUS, RSIE); + RO_FIELD(CR_STATUS, NMI); + WR_FIELD(CR_STATUS, PRS); + RO_FIELD(CR_STATUS, CRS); + WR_FIELD(CR_STATUS, IL); + WR_FIELD(CR_STATUS, IH); + } else { + RO_FIELD(CR_STATUS, RSIE); + WR_REG(CR_IENABLE); + RO_REG(CR_IPENDING); + } if (cpu->mmu_present) { WR_FIELD(CR_STATUS, U); diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c index e656986e3c..42342f007f 100644 --- a/target/nios2/op_helper.c +++ b/target/nios2/op_helper.c @@ -34,7 +34,25 @@ void helper_raise_exception(CPUNios2State *env, uint32_t index) #ifndef CONFIG_USER_ONLY void helper_eret(CPUNios2State *env, uint32_t new_pc) { - env->status = env->estatus; + Nios2CPU *cpu = env_archcpu(env); + unsigned crs = FIELD_EX32(env->status, CR_STATUS, CRS); + uint32_t val; + + if (crs == 0) { + val = env->estatus; + } else { + val = env->shadow_regs[crs][R_SSTATUS]; + } + + /* + * Both estatus and sstatus have no constraints on write; + * do not allow reserved fields in status to be set. + */ + val &= (cpu->cr_state[CR_STATUS].writable | + cpu->cr_state[CR_STATUS].readonly); + env->status = val; + nios2_update_crs(env); + env->pc = new_pc; cpu_loop_exit(env_cpu(env)); } -- 2.25.1