[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v8 58/68] target/nios2: Implement rdprs, wrprs
From: |
Richard Henderson |
Subject: |
[PATCH v8 58/68] target/nios2: Implement rdprs, wrprs |
Date: |
Fri, 22 Apr 2022 09:52:28 -0700 |
Implement these out of line, so that tcg global temps
(aka the architectural registers) are synced back to
tcg storage as required. This makes sure that we get
the proper results when status.PRS == status.CRS.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20220421151735.31996-55-richard.henderson@linaro.org>
---
target/nios2/cpu.h | 1 +
target/nios2/helper.h | 2 ++
target/nios2/op_helper.c | 16 +++++++++++
target/nios2/translate.c | 57 ++++++++++++++++++++++++++++++++++++++--
4 files changed, 74 insertions(+), 2 deletions(-)
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index f6efaa79b3..cca821cf80 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -220,6 +220,7 @@ struct ArchCPU {
bool diverr_present;
bool mmu_present;
+ bool eic_present;
uint32_t pid_num_bits;
uint32_t tlb_num_ways;
diff --git a/target/nios2/helper.h b/target/nios2/helper.h
index 6f5ec60b0d..1648d76ade 100644
--- a/target/nios2/helper.h
+++ b/target/nios2/helper.h
@@ -24,6 +24,8 @@ DEF_HELPER_FLAGS_3(divu, TCG_CALL_NO_WG, i32, env, i32, i32)
#if !defined(CONFIG_USER_ONLY)
DEF_HELPER_3(eret, noreturn, env, i32, i32)
+DEF_HELPER_FLAGS_2(rdprs, TCG_CALL_NO_WG, i32, env, i32)
+DEF_HELPER_3(wrprs, void, env, i32, i32)
DEF_HELPER_2(mmu_write_tlbacc, void, env, i32)
DEF_HELPER_2(mmu_write_tlbmisc, void, env, i32)
DEF_HELPER_2(mmu_write_pteaddr, void, env, i32)
diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c
index 38a71a1f2d..a3164f5356 100644
--- a/target/nios2/op_helper.c
+++ b/target/nios2/op_helper.c
@@ -83,4 +83,20 @@ void helper_eret(CPUNios2State *env, uint32_t new_status,
uint32_t new_pc)
env->pc = new_pc;
cpu_loop_exit(cs);
}
+
+/*
+ * RDPRS and WRPRS are implemented out of line so that if PRS == CRS,
+ * all of the tcg global temporaries are synced back to ENV.
+ */
+uint32_t helper_rdprs(CPUNios2State *env, uint32_t regno)
+{
+ unsigned prs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, PRS);
+ return env->shadow_regs[prs][regno];
+}
+
+void helper_wrprs(CPUNios2State *env, uint32_t regno, uint32_t val)
+{
+ unsigned prs = FIELD_EX32(env->ctrl[CR_STATUS], CR_STATUS, PRS);
+ env->shadow_regs[prs][regno] = val;
+}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 363f2ea3ca..e566175db5 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -130,6 +130,7 @@ typedef struct DisasContext {
uint32_t tb_flags;
TCGv sink;
const ControlRegState *cr_state;
+ bool eic_present;
} DisasContext;
static TCGv cpu_R[NUM_GP_REGS];
@@ -387,6 +388,27 @@ gen_i_math_logic(andhi, andi, 0, imm_shifted)
gen_i_math_logic(orhi , ori, 1, imm_shifted)
gen_i_math_logic(xorhi, xori, 1, imm_shifted)
+/* rB <- prs.rA + sigma(IMM16) */
+static void rdprs(DisasContext *dc, uint32_t code, uint32_t flags)
+{
+ if (!dc->eic_present) {
+ t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+ return;
+ }
+ if (!gen_check_supervisor(dc)) {
+ return;
+ }
+
+#ifdef CONFIG_USER_ONLY
+ g_assert_not_reached();
+#else
+ I_TYPE(instr, code);
+ TCGv dest = dest_gpr(dc, instr.b);
+ gen_helper_rdprs(dest, cpu_env, tcg_constant_i32(instr.a));
+ tcg_gen_addi_tl(dest, dest, instr.imm16.s);
+#endif
+}
+
/* Prototype only, defined below */
static void handle_r_type_instr(DisasContext *dc, uint32_t code,
uint32_t flags);
@@ -448,7 +470,7 @@ static const Nios2Instruction i_type_instructions[] = {
INSTRUCTION_FLG(gen_stx, MO_SL), /* stwio */
INSTRUCTION_FLG(gen_bxx, TCG_COND_LTU), /* bltu */
INSTRUCTION_FLG(gen_ldx, MO_UL), /* ldwio */
- INSTRUCTION_UNIMPLEMENTED(), /* rdprs */
+ INSTRUCTION(rdprs), /* rdprs */
INSTRUCTION_ILLEGAL(),
INSTRUCTION_FLG(handle_r_type_instr, 0), /* R-Type */
INSTRUCTION_NOP(), /* flushd */
@@ -648,6 +670,36 @@ static void wrctl(DisasContext *dc, uint32_t code,
uint32_t flags)
#endif
}
+/* prs.rC <- rA */
+static void wrprs(DisasContext *dc, uint32_t code, uint32_t flags)
+{
+ if (!dc->eic_present) {
+ t_gen_helper_raise_exception(dc, EXCP_ILLEGAL);
+ return;
+ }
+ if (!gen_check_supervisor(dc)) {
+ return;
+ }
+
+#ifdef CONFIG_USER_ONLY
+ g_assert_not_reached();
+#else
+ R_TYPE(instr, code);
+ gen_helper_wrprs(cpu_env, tcg_constant_i32(instr.c),
+ load_gpr(dc, instr.a));
+ /*
+ * The expected write to PRS[r0] is 0, from CRS[r0].
+ * If not, and CRS == PRS (which we cannot tell from here),
+ * we may now have a non-zero value in our current r0.
+ * By ending the TB, we re-evaluate tb_flags and find out.
+ */
+ if (instr.c == 0
+ && (instr.a != 0 || !FIELD_EX32(dc->tb_flags, TBFLAGS, R0_0))) {
+ dc->base.is_jmp = DISAS_UPDATE;
+ }
+#endif
+}
+
/* Comparison instructions */
static void gen_cmpxx(DisasContext *dc, uint32_t code, uint32_t flags)
{
@@ -793,7 +845,7 @@ static const Nios2Instruction r_type_instructions[] = {
INSTRUCTION_ILLEGAL(),
INSTRUCTION(slli), /* slli */
INSTRUCTION(sll), /* sll */
- INSTRUCTION_UNIMPLEMENTED(), /* wrprs */
+ INSTRUCTION(wrprs), /* wrprs */
INSTRUCTION_ILLEGAL(),
INSTRUCTION(or), /* or */
INSTRUCTION(mulxsu), /* mulxsu */
@@ -895,6 +947,7 @@ static void nios2_tr_init_disas_context(DisasContextBase
*dcbase, CPUState *cs)
dc->mem_idx = cpu_mmu_index(env, false);
dc->cr_state = cpu->cr_state;
dc->tb_flags = dc->base.tb->flags;
+ dc->eic_present = cpu->eic_present;
/* Bound the number of insns to execute to those left on the page. */
page_insns = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
--
2.34.1
- [PATCH v8 49/68] target/nios2: Introduce dest_gpr, (continued)
- [PATCH v8 49/68] target/nios2: Introduce dest_gpr, Richard Henderson, 2022/04/22
- [PATCH v8 51/68] target/nios2: Enable unaligned traps for system mode, Richard Henderson, 2022/04/22
- [PATCH v8 52/68] target/nios2: Create gen_jumpr, Richard Henderson, 2022/04/22
- [PATCH v8 50/68] target/nios2: Drop CR_STATUS_EH from tb->flags, Richard Henderson, 2022/04/22
- [PATCH v8 54/68] target/nios2: Use gen_goto_tb for DISAS_TOO_MANY, Richard Henderson, 2022/04/22
- [PATCH v8 53/68] target/nios2: Hoist set of is_jmp into gen_goto_tb, Richard Henderson, 2022/04/22
- [PATCH v8 56/68] target/nios2: Implement Misaligned destination exception, Richard Henderson, 2022/04/22
- [PATCH v8 55/68] target/nios2: Use tcg_gen_lookup_and_goto_ptr, Richard Henderson, 2022/04/22
- [PATCH v8 57/68] target/nios2: Introduce shadow register sets, Richard Henderson, 2022/04/22
- [PATCH v8 59/68] target/nios2: Update helper_eret for shadow registers, Richard Henderson, 2022/04/22
- [PATCH v8 58/68] target/nios2: Implement rdprs, wrprs,
Richard Henderson <=
- [PATCH v8 60/68] target/nios2: Implement EIC interrupt processing, Richard Henderson, 2022/04/22
- [PATCH v8 61/68] target/nios2: Advance pc when raising exceptions, Richard Henderson, 2022/04/22
- [PATCH v8 62/68] linux-user/nios2: Handle various SIGILL exceptions, Richard Henderson, 2022/04/22
- [PATCH v8 63/68] hw/intc: Vectored Interrupt Controller (VIC), Richard Henderson, 2022/04/22
- [PATCH v8 64/68] hw/nios2: Introduce Nios2MachineState, Richard Henderson, 2022/04/22
- [PATCH v8 66/68] hw/nios2: Machine with a Vectored Interrupt Controller, Richard Henderson, 2022/04/22
- [PATCH v8 65/68] hw/nios2: Move memory regions into Nios2Machine, Richard Henderson, 2022/04/22
- [PATCH v8 67/68] tests/tcg/nios2: Add semihosting multiarch tests, Richard Henderson, 2022/04/22
- [PATCH v8 68/68] tests/tcg/nios2: Add test-shadow-1, Richard Henderson, 2022/04/22