diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-04-21 08:17:26 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2022-04-26 08:17:05 -0700 |
commit | 6bcc59cafa271b634009bc92c01c866602ea4c53 (patch) | |
tree | 0e2c31cfcc8dcd770891449cb173545c2da6d8f0 | |
parent | 3a03087019ab4a67751570190439d252b39b83c4 (diff) | |
download | qemu-6bcc59cafa271b634009bc92c01c866602ea4c53.zip qemu-6bcc59cafa271b634009bc92c01c866602ea4c53.tar.gz qemu-6bcc59cafa271b634009bc92c01c866602ea4c53.tar.bz2 |
target/nios2: Update helper_eret for shadow registers
When CRS = 0, we restore from estatus; otherwise from sstatus.
Update for the new CRS.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220421151735.31996-56-richard.henderson@linaro.org>
-rw-r--r-- | target/nios2/cpu.h | 1 | ||||
-rw-r--r-- | target/nios2/op_helper.c | 10 | ||||
-rw-r--r-- | target/nios2/translate.c | 13 |
3 files changed, 16 insertions, 8 deletions
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h index cca821c..eb171a3 100644 --- a/target/nios2/cpu.h +++ b/target/nios2/cpu.h @@ -82,6 +82,7 @@ enum { R_FP = 28, R_EA = 29, R_BA = 30, + R_SSTATUS = 30, R_RA = 31, }; diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c index a3164f5..9404010 100644 --- a/target/nios2/op_helper.c +++ b/target/nios2/op_helper.c @@ -73,14 +73,18 @@ void helper_eret(CPUNios2State *env, uint32_t new_status, uint32_t new_pc) } /* - * Both estatus and bstatus have no constraints on write; + * None of estatus, bstatus, or sstatus have constraints on write; * do not allow reserved fields in status to be set. - * TODO: more than this is required for shadow registers. + * When shadow registers are enabled, eret *does* restore CRS. + * Rather than testing eic_present to decide, mask CRS out of + * the set of readonly fields. */ - new_status &= cpu->cr_state[CR_STATUS].writable; + new_status &= cpu->cr_state[CR_STATUS].writable | + (cpu->cr_state[CR_STATUS].readonly & R_CR_STATUS_CRS_MASK); env->ctrl[CR_STATUS] = new_status; env->pc = new_pc; + nios2_update_crs(env); cpu_loop_exit(cs); } diff --git a/target/nios2/translate.c b/target/nios2/translate.c index e566175..b52f981 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -496,11 +496,14 @@ static void eret(DisasContext *dc, uint32_t code, uint32_t flags) #ifdef CONFIG_USER_ONLY g_assert_not_reached(); #else - TCGv tmp = tcg_temp_new(); - tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPUNios2State, ctrl[CR_ESTATUS])); - gen_helper_eret(cpu_env, tmp, load_gpr(dc, R_EA)); - tcg_temp_free(tmp); - + if (FIELD_EX32(dc->tb_flags, TBFLAGS, CRS0)) { + TCGv tmp = tcg_temp_new(); + tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPUNios2State, ctrl[CR_ESTATUS])); + gen_helper_eret(cpu_env, tmp, load_gpr(dc, R_EA)); + tcg_temp_free(tmp); + } else { + gen_helper_eret(cpu_env, load_gpr(dc, R_SSTATUS), load_gpr(dc, R_EA)); + } dc->base.is_jmp = DISAS_NORETURN; #endif } |