From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1MQk0S-0002Hc-7c for qemu-devel@nongnu.org; Tue, 14 Jul 2009 11:33:24 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1MQk0N-0002AY-Cq for qemu-devel@nongnu.org; Tue, 14 Jul 2009 11:33:23 -0400 Received: from [199.232.76.173] (port=34888 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1MQk0M-00029i-Gm for qemu-devel@nongnu.org; Tue, 14 Jul 2009 11:33:18 -0400 Received: from mx20.gnu.org ([199.232.41.8]:15875) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1MQk0M-0007Xd-0p for qemu-devel@nongnu.org; Tue, 14 Jul 2009 11:33:18 -0400 Received: from mail.codesourcery.com ([65.74.133.4]) by mx20.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1MQk0K-00062z-IR for qemu-devel@nongnu.org; Tue, 14 Jul 2009 11:33:16 -0400 From: Nathan Froyd Date: Tue, 14 Jul 2009 08:33:11 -0700 Message-Id: <1247585591-25601-1-git-send-email-froydnj@codesourcery.com> Subject: [Qemu-devel] [PATCH] target-mips: fix single-stepping List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Single-stepping branches on MIPS didn't work right, because the generation of EXCP_DEBUG happened after the generation of the code to exit the current TB. That is, given the code: bne v0,v1,target nop ... target: addu v0,v0,v1 1: when you single-stepped through the NOP, execution wouldn't actually halt until you reached the label `1'. This patch corrects that and also changes single-stepping so that a branch and its delay slot are executed as one instruction for the purposes of single-stepping. This behavior is comparable to what other MIPS tools (e.g. MIPSsim with MDI) do. GDB avoids placing breakpoints in branch delay slots, so this change doesn't break anything on the GDB side. Signed-off-by: Nathan Froyd --- target-mips/translate.c | 21 ++++++++++++++++++--- 1 files changed, 18 insertions(+), 3 deletions(-) diff --git a/target-mips/translate.c b/target-mips/translate.c index 2eee11b..0bcaf6d 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -464,6 +464,7 @@ typedef struct DisasContext { struct TranslationBlock *tb; target_ulong pc, saved_pc; uint32_t opcode; + int singlestep_enabled; /* Routine used to access memory */ int mem_idx; uint32_t hflags, saved_hflags; @@ -2460,12 +2461,17 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest) { TranslationBlock *tb; tb = ctx->tb; - if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { + if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && + likely(!ctx->singlestep_enabled)) { tcg_gen_goto_tb(n); gen_save_pc(dest); tcg_gen_exit_tb((long)tb + n); } else { gen_save_pc(dest); + if (ctx->singlestep_enabled) { + save_cpu_state(ctx, 0); + gen_helper_0i(raise_exception, EXCP_DEBUG); + } tcg_gen_exit_tb(0); } } @@ -8264,6 +8270,10 @@ static void decode_opc (CPUState *env, DisasContext *ctx) /* unconditional branch to register */ MIPS_DEBUG("branch to register"); tcg_gen_mov_tl(cpu_PC, btarget); + if (ctx->singlestep_enabled) { + save_cpu_state(ctx, 0); + gen_helper_0i(raise_exception, EXCP_DEBUG); + } tcg_gen_exit_tb(0); break; default: @@ -8293,6 +8303,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, gen_opc_end = gen_opc_buf + OPC_MAX_SIZE - 16; ctx.pc = pc_start; ctx.saved_pc = -1; + ctx.singlestep_enabled = env->singlestep_enabled; ctx.tb = tb; ctx.bstate = BS_NONE; /* Restore delay slot state from the tb context. */ @@ -8348,7 +8359,11 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, ctx.pc += 4; num_insns++; - if (env->singlestep_enabled) + /* 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 (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) break; if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0) @@ -8365,7 +8380,7 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb, } if (tb->cflags & CF_LAST_IO) gen_io_end(); - if (env->singlestep_enabled) { + if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) { save_cpu_state(&ctx, ctx.bstate == BS_NONE); gen_helper_0i(raise_exception, EXCP_DEBUG); } else { -- 1.6.3.2