diff options
author | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-10 23:28:14 +0000 |
---|---|---|
committer | aurel32 <aurel32@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-05-10 23:28:14 +0000 |
commit | 8cbcb4fa2c6d5fb84552ab141c6e35d33323aa18 (patch) | |
tree | 4983eb4edde1884f94d9c7b7a8b55125fd12d91c /target-ppc/translate.c | |
parent | 33759846482cc4a3a0398972bf942fecd0fd78db (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
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 62 |
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); } |