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
This commit is contained in:
aurel32 2008-05-10 23:28:14 +00:00
parent 3375984648
commit 8cbcb4fa2c
1 changed files with 39 additions and 23 deletions

View File

@ -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);
}