aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-10 23:28:14 +0000
committeraurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162>2008-05-10 23:28:14 +0000
commit8cbcb4fa2c6d5fb84552ab141c6e35d33323aa18 (patch)
tree4983eb4edde1884f94d9c7b7a8b55125fd12d91c
parent33759846482cc4a3a0398972bf942fecd0fd78db (diff)
Fix broken PPC user space single stepping
(Jason Wessel) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4421 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--target-ppc/translate.c62
1 files changed, 39 insertions, 23 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 2c27f20af7..4e71614f7b 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -29,6 +29,10 @@
#include "tcg-op.h"
#include "qemu-common.h"
+#define CPU_SINGLE_STEP 0x1
+#define CPU_BRANCH_STEP 0x2
+#define GDBSTUB_SINGLE_STEP 0x4
+
/* Include definitions for instructions classes and implementations flags */
//#define DO_SINGLE_STEP
//#define PPC_DEBUG_DISAS
@@ -2785,7 +2789,7 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n,
TranslationBlock *tb;
tb = ctx->tb;
if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
- !ctx->singlestep_enabled) {
+ likely(!ctx->singlestep_enabled)) {
tcg_gen_goto_tb(n);
gen_set_T1(dest);
#if defined(TARGET_PPC64)
@@ -2803,8 +2807,20 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n,
else
#endif
gen_op_b_T1();
- if (ctx->singlestep_enabled)
- gen_op_debug();
+ if (unlikely(ctx->singlestep_enabled)) {
+ if ((ctx->singlestep_enabled &
+ (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
+ ctx->exception == POWERPC_EXCP_BRANCH) {
+ target_ulong tmp = ctx->nip;
+ ctx->nip = dest;
+ GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
+ ctx->nip = tmp;
+ }
+ if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
+ gen_update_nip(ctx, dest);
+ gen_op_debug();
+ }
+ }
tcg_gen_exit_tb(0);
}
}
@@ -2824,6 +2840,7 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
{
target_ulong li, target;
+ ctx->exception = POWERPC_EXCP_BRANCH;
/* sign extend LI */
#if defined(TARGET_PPC64)
if (ctx->sf_mode)
@@ -2842,7 +2859,6 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
if (LK(ctx->opcode))
gen_setlr(ctx, ctx->nip);
gen_goto_tb(ctx, 0, target);
- ctx->exception = POWERPC_EXCP_BRANCH;
}
#define BCOND_IM 0
@@ -2857,6 +2873,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type)
uint32_t bi = BI(ctx->opcode);
uint32_t mask;
+ ctx->exception = POWERPC_EXCP_BRANCH;
if ((bo & 0x4) == 0)
gen_op_dec_ctr();
switch(type) {
@@ -2906,7 +2923,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type)
case 6:
if (type == BCOND_IM) {
gen_goto_tb(ctx, 0, target);
- goto out;
+ return;
} else {
#if defined(TARGET_PPC64)
if (ctx->sf_mode)
@@ -2985,12 +3002,12 @@ static always_inline void gen_bcond (DisasContext *ctx, int type)
#endif
gen_op_btest_T1(ctx->nip);
no_test:
- if (ctx->singlestep_enabled)
+ if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
+ gen_update_nip(ctx, ctx->nip);
gen_op_debug();
+ }
tcg_gen_exit_tb(0);
}
- out:
- ctx->exception = POWERPC_EXCP_BRANCH;
}
GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
@@ -6150,7 +6167,6 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
target_ulong pc_start;
uint16_t *gen_opc_end;
int supervisor, little_endian;
- int single_step, branch_step;
int j, lj = -1;
pc_start = tb->pc;
@@ -6184,14 +6200,13 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
else
ctx.altivec_enabled = 0;
if ((env->flags & POWERPC_FLAG_SE) && msr_se)
- single_step = 1;
+ ctx.singlestep_enabled = CPU_SINGLE_STEP;
else
- single_step = 0;
+ ctx.singlestep_enabled = 0;
if ((env->flags & POWERPC_FLAG_BE) && msr_be)
- branch_step = 1;
- else
- branch_step = 0;
- ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1;
+ ctx.singlestep_enabled |= CPU_BRANCH_STEP;
+ if (unlikely(env->singlestep_enabled))
+ ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
#if defined (DO_SINGLE_STEP) && 0
/* Single step trace mode */
msr_se = 1;
@@ -6284,14 +6299,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
handler->count++;
#endif
/* Check trace mode exceptions */
- if (unlikely(branch_step != 0 &&
- ctx.exception == POWERPC_EXCP_BRANCH)) {
- GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
- } else if (unlikely(single_step != 0 &&
- (ctx.nip <= 0x100 || ctx.nip > 0xF00 ||
- (ctx.nip & 0xFC) != 0x04) &&
- ctx.exception != POWERPC_SYSCALL &&
- ctx.exception != POWERPC_EXCP_TRAP)) {
+ if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
+ (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
+ ctx.exception != POWERPC_SYSCALL &&
+ ctx.exception != POWERPC_EXCP_TRAP &&
+ ctx.exception != POWERPC_EXCP_BRANCH)) {
GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
} else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
(env->singlestep_enabled))) {
@@ -6307,6 +6319,10 @@ static always_inline int gen_intermediate_code_internal (CPUState *env,
if (ctx.exception == POWERPC_EXCP_NONE) {
gen_goto_tb(&ctx, 0, ctx.nip);
} else if (ctx.exception != POWERPC_EXCP_BRANCH) {
+ if (unlikely(env->singlestep_enabled)) {
+ gen_update_nip(&ctx, ctx.nip);
+ gen_op_debug();
+ }
/* Generate the return instruction */
tcg_gen_exit_tb(0);
}