aboutsummaryrefslogtreecommitdiff
path: root/target/microblaze/helper.c
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2020-08-20 20:29:01 -0700
committerRichard Henderson <richard.henderson@linaro.org>2020-09-01 07:43:35 -0700
commitab0c8d0f5b3377eba2c14116e199573583ea0089 (patch)
tree48fd6496c539bc41bccce03399542336767a6365 /target/microblaze/helper.c
parent2271a6ac0a075d859b71551626e3cae9817ba7da (diff)
target/microblaze: Use cc->do_unaligned_access
This fixes the problem in which unaligned stores succeeded, but then we raised the exception after modifying memory. Store the ESS for the unaligned data access in the iflags for the insn, so that it can be found during unwind. Tested-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/microblaze/helper.c')
-rw-r--r--target/microblaze/helper.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/target/microblaze/helper.c b/target/microblaze/helper.c
index 06f4322e09..0e3be251a7 100644
--- a/target/microblaze/helper.c
+++ b/target/microblaze/helper.c
@@ -296,3 +296,31 @@ bool mb_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
}
return false;
}
+
+void mb_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
+ MMUAccessType access_type,
+ int mmu_idx, uintptr_t retaddr)
+{
+ MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
+ uint32_t esr, iflags;
+
+ /* Recover the pc and iflags from the corresponding insn_start. */
+ cpu_restore_state(cs, retaddr, true);
+ iflags = cpu->env.iflags;
+
+ qemu_log_mask(CPU_LOG_INT,
+ "Unaligned access addr=" TARGET_FMT_lx
+ " pc=%x iflags=%x\n", addr, cpu->env.pc, iflags);
+
+ esr = ESR_EC_UNALIGNED_DATA;
+ if (likely(iflags & ESR_ESS_FLAG)) {
+ esr |= iflags & ESR_ESS_MASK;
+ } else {
+ qemu_log_mask(LOG_UNIMP, "Unaligned access without ESR_ESS_FLAG\n");
+ }
+
+ cpu->env.ear = addr;
+ cpu->env.esr = esr;
+ cs->exception_index = EXCP_HW_EXCP;
+ cpu_loop_exit(cs);
+}