From 3d35bcc2135faefa7565f1023ce3e7df9032aedc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 31 Aug 2020 10:08:20 -0700 Subject: target/microblaze: Handle DISAS_EXIT_NEXT in delay slot It is legal to put an mts instruction into a delay slot. We should continue to return to the main loop in that case so that we recognize any pending interrupts. Reviewed-by: Edgar E. Iglesias Tested-by: Edgar E. Iglesias Signed-off-by: Richard Henderson --- target/microblaze/translate.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index 6bf299a826..608d413c83 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -1696,6 +1696,10 @@ static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) dc->base.pc_next += 4; if (dc->jmp_cond != TCG_COND_NEVER && !(dc->tb_flags & D_FLAG)) { + /* + * Finish any return-from branch. + * TODO: Diagnose rtXd in delay slot of rtYd earlier. + */ if (dc->tb_flags & DRTI_FLAG) { do_rti(dc); } else if (dc->tb_flags & DRTB_FLAG) { @@ -1703,7 +1707,35 @@ static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs) } else if (dc->tb_flags & DRTE_FLAG) { do_rte(dc); } - dc->base.is_jmp = DISAS_JUMP; + + /* Complete the branch, ending the TB. */ + switch (dc->base.is_jmp) { + case DISAS_NORETURN: + /* + * E.g. illegal insn in a delay slot. We've already exited + * and will handle D_FLAG in mb_cpu_do_interrupt. + */ + break; + case DISAS_EXIT: + /* + * TODO: diagnose brk/brki in delay slot earlier. + * This would then fold into the illegal insn case above. + */ + break; + case DISAS_NEXT: + /* Normal insn a delay slot. */ + dc->base.is_jmp = DISAS_JUMP; + break; + case DISAS_EXIT_NEXT: + /* + * E.g. mts insn in a delay slot. Continue with btarget, + * but still return to the main loop. + */ + dc->base.is_jmp = DISAS_EXIT_JUMP; + break; + default: + g_assert_not_reached(); + } } } -- cgit v1.2.3