From: Richard Henderson Date: Tue, 20 Jul 2021 00:01:49 +0000 (-1000) Subject: target/mips: Fix single stepping X-Git-Tag: v6.2.0-rc0~51^2~11 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ef00cd4a22701923583862c48448b43bbcdaca0f;p=thirdparty%2Fqemu.git target/mips: Fix single stepping As per an ancient comment in mips_tr_translate_insn about the expectations of gdb, when restarting the insn in a delay slot we also re-execute the branch. Which means that we are expected to execute two insns in this case. This has been broken since 8b86d6d2580, where we forced max_insns to 1 while single-stepping. This resulted in an exit from the translator loop after the branch but before the delay slot is translated. Increase the max_insns to 2 for this case. In addition, bypass the end-of-page check, for when the branch itself ends the page. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 148afec9dc0..f239f9ffc06 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -16016,6 +16016,16 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 | INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN; + /* + * Execute a branch and its delay slot as a single instruction. + * This is what GDB expects and is consistent with what the + * hardware does (e.g. if a delay slot instruction faults, the + * reported PC is the PC of the branch). + */ + if (ctx->base.singlestep_enabled && (ctx->hflags & MIPS_HFLAG_BMASK)) { + ctx->base.max_insns = 2; + } + LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx, ctx->hflags); } @@ -16085,17 +16095,14 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (ctx->base.is_jmp != DISAS_NEXT) { return; } + /* - * Execute a branch and its delay slot as a single instruction. - * This is what GDB expects and is consistent with what the - * hardware does (e.g. if a delay slot instruction faults, the - * reported PC is the PC of the branch). + * End the TB on (most) page crossings. + * See mips_tr_init_disas_context about single-stepping a branch + * together with its delay slot. */ - if (ctx->base.singlestep_enabled && - (ctx->hflags & MIPS_HFLAG_BMASK) == 0) { - ctx->base.is_jmp = DISAS_TOO_MANY; - } - if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) { + if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE + && !ctx->base.singlestep_enabled) { ctx->base.is_jmp = DISAS_TOO_MANY; } }