[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v7 57/64] target/nios2: Advance pc when raising exceptions
From: |
Richard Henderson |
Subject: |
[PATCH v7 57/64] target/nios2: Advance pc when raising exceptions |
Date: |
Thu, 21 Apr 2022 08:17:28 -0700 |
The exception return address for nios2 is the instruction
after the one that was executing at the time of the exception.
We have so far implemented this by advancing the pc during the
process of raising the exception. It is perhaps a little less
confusing to do this advance in the translator (and helpers)
when raising the exception in the first place, so that we may
more closely match kernel sources.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/nios2/cpu.h | 2 ++
linux-user/nios2/cpu_loop.c | 8 ++------
target/nios2/helper.c | 13 +++++++------
target/nios2/op_helper.c | 18 ++++++++++++++++--
target/nios2/translate.c | 6 +++---
5 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/target/nios2/cpu.h b/target/nios2/cpu.h
index e25d3cdb11..58d56e55f9 100644
--- a/target/nios2/cpu.h
+++ b/target/nios2/cpu.h
@@ -266,6 +266,8 @@ hwaddr nios2_cpu_get_phys_page_debug(CPUState *cpu, vaddr
addr);
void nios2_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
MMUAccessType access_type, int mmu_idx,
uintptr_t retaddr) QEMU_NORETURN;
+void nios2_cpu_loop_exit_advance(CPUNios2State *env, uintptr_t retaddr)
+ QEMU_NORETURN;
void do_nios2_semihosting(CPUNios2State *env);
diff --git a/linux-user/nios2/cpu_loop.c b/linux-user/nios2/cpu_loop.c
index 30a27f252b..a5e86990e2 100644
--- a/linux-user/nios2/cpu_loop.c
+++ b/linux-user/nios2/cpu_loop.c
@@ -39,6 +39,8 @@ void cpu_loop(CPUNios2State *env)
break;
case EXCP_DIV:
+ /* Match kernel's handle_diverror_c(). */
+ env->pc -= 4;
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
break;
@@ -49,12 +51,6 @@ void cpu_loop(CPUNios2State *env)
break;
case EXCP_TRAP:
- /*
- * TODO: This advance should be done in the translator, as
- * hardware produces an advanced pc as part of all exceptions.
- */
- env->pc += 4;
-
switch (env->error_code) {
case 0:
qemu_log_mask(CPU_LOG_INT, "\nSyscall\n");
diff --git a/target/nios2/helper.c b/target/nios2/helper.c
index e256d1528e..bb3b09e5a7 100644
--- a/target/nios2/helper.c
+++ b/target/nios2/helper.c
@@ -49,7 +49,7 @@ static void do_exception(Nios2CPU *cpu, uint32_t
exception_addr,
cr_es = CR_BSTATUS;
}
env->ctrl[cr_es] = old_status;
- env->regs[r_ea] = env->pc + 4;
+ env->regs[r_ea] = env->pc;
if (cpu->mmu_present) {
new_status |= CR_STATUS_EH;
@@ -113,7 +113,7 @@ static void do_eic_irq(Nios2CPU *cpu)
}
env->shadow_regs[new_rs][R_SSTATUS] = old_status;
}
- env->shadow_regs[new_rs][R_EA] = env->pc + 4;
+ env->shadow_regs[new_rs][R_EA] = env->pc;
}
env->ctrl[CR_STATUS] = new_status;
@@ -187,6 +187,8 @@ void nios2_cpu_do_interrupt(CPUState *cs)
switch (cs->exception_index) {
case EXCP_IRQ:
+ /* Note that PC is advanced for interrupts as well. */
+ env->pc += 4;
if (cpu->eic_present) {
do_eic_irq(cpu);
} else {
@@ -249,7 +251,6 @@ void nios2_cpu_do_interrupt(CPUState *cs)
break;
case EXCP_SEMIHOST:
- env->pc += 4;
do_nios2_semihosting(env);
break;
@@ -291,7 +292,7 @@ void nios2_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
env->ctrl[CR_BADADDR] = addr;
cs->exception_index = EXCP_UNALIGN;
- cpu_loop_exit_restore(cs, retaddr);
+ nios2_cpu_loop_exit_advance(env, retaddr);
}
bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
@@ -330,7 +331,7 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int
size,
cs->exception_index = (access_type == MMU_INST_FETCH
? EXCP_SUPERA_X : EXCP_SUPERA_D);
env->ctrl[CR_BADADDR] = address;
- cpu_loop_exit_restore(cs, retaddr);
+ nios2_cpu_loop_exit_advance(env, retaddr);
}
}
@@ -367,5 +368,5 @@ bool nios2_cpu_tlb_fill(CPUState *cs, vaddr address, int
size,
cs->exception_index = excp;
env->ctrl[CR_BADADDR] = address;
- cpu_loop_exit_restore(cs, retaddr);
+ nios2_cpu_loop_exit_advance(env, retaddr);
}
diff --git a/target/nios2/op_helper.c b/target/nios2/op_helper.c
index 94040102f4..2e30d0a908 100644
--- a/target/nios2/op_helper.c
+++ b/target/nios2/op_helper.c
@@ -31,6 +31,20 @@ void helper_raise_exception(CPUNios2State *env, uint32_t
index)
cpu_loop_exit(cs);
}
+void nios2_cpu_loop_exit_advance(CPUNios2State *env, uintptr_t retaddr)
+{
+ CPUState *cs = env_cpu(env);
+
+ /*
+ * Note that PC is advanced for all hardware exceptions.
+ * Do this here, rather than in restore_state_to_opc(),
+ * lest we affect QEMU internal exceptions, like EXCP_DEBUG.
+ */
+ cpu_restore_state(cs, retaddr, true);
+ env->pc += 4;
+ cpu_loop_exit(cs);
+}
+
static void maybe_raise_div(CPUNios2State *env, uintptr_t ra)
{
Nios2CPU *cpu = env_archcpu(env);
@@ -38,7 +52,7 @@ static void maybe_raise_div(CPUNios2State *env, uintptr_t ra)
if (cpu->diverr_present) {
cs->exception_index = EXCP_DIV;
- cpu_loop_exit_restore(cs, ra);
+ nios2_cpu_loop_exit_advance(env, ra);
}
}
@@ -69,7 +83,7 @@ void helper_eret(CPUNios2State *env, uint32_t new_status,
uint32_t new_pc)
if (unlikely(new_pc & 3)) {
env->ctrl[CR_BADADDR] = new_pc;
cs->exception_index = EXCP_UNALIGND;
- cpu_loop_exit_restore(cs, GETPC());
+ nios2_cpu_loop_exit_advance(env, GETPC());
}
/*
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
index 29cb610aca..c06e9e7b14 100644
--- a/target/nios2/translate.c
+++ b/target/nios2/translate.c
@@ -196,10 +196,10 @@ static TCGv dest_gpr(DisasContext *dc, unsigned reg)
#endif
}
-static void t_gen_helper_raise_exception(DisasContext *dc,
- uint32_t index)
+static void t_gen_helper_raise_exception(DisasContext *dc, uint32_t index)
{
- tcg_gen_movi_tl(cpu_pc, dc->pc);
+ /* Note that PC is advanced for all hardware exceptions. */
+ tcg_gen_movi_tl(cpu_pc, dc->base.pc_next);
gen_helper_raise_exception(cpu_env, tcg_constant_i32(index));
dc->base.is_jmp = DISAS_NORETURN;
}
--
2.34.1
- [PATCH v7 56/64] target/nios2: Implement EIC interrupt processing, (continued)
- [PATCH v7 56/64] target/nios2: Implement EIC interrupt processing, Richard Henderson, 2022/04/21
- [PATCH v7 55/64] target/nios2: Update helper_eret for shadow registers, Richard Henderson, 2022/04/21
- [PATCH v7 59/64] hw/intc: Vectored Interrupt Controller (VIC), Richard Henderson, 2022/04/21
- [PATCH v7 64/64] tests/tcg/nios2: Add test-shadow-1, Richard Henderson, 2022/04/21
- [PATCH v7 53/64] target/nios2: Introduce shadow register sets, Richard Henderson, 2022/04/21
- [PATCH v7 60/64] hw/nios2: Introduce Nios2MachineState, Richard Henderson, 2022/04/21
- [PATCH v7 54/64] target/nios2: Implement rdprs, wrprs, Richard Henderson, 2022/04/21
- [PATCH v7 57/64] target/nios2: Advance pc when raising exceptions,
Richard Henderson <=
- [PATCH v7 62/64] hw/nios2: Machine with a Vectored Interrupt Controller, Richard Henderson, 2022/04/21
- [PATCH v7 63/64] tests/tcg/nios2: Add semihosting multiarch tests, Richard Henderson, 2022/04/21