Commit 8cbcb4fa2c6d5fb84552ab141c6e35d33323aa18
1 parent
33759846
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
Showing
1 changed file
with
39 additions
and
23 deletions
target-ppc/translate.c
... | ... | @@ -29,6 +29,10 @@ |
29 | 29 | #include "tcg-op.h" |
30 | 30 | #include "qemu-common.h" |
31 | 31 | |
32 | +#define CPU_SINGLE_STEP 0x1 | |
33 | +#define CPU_BRANCH_STEP 0x2 | |
34 | +#define GDBSTUB_SINGLE_STEP 0x4 | |
35 | + | |
32 | 36 | /* Include definitions for instructions classes and implementations flags */ |
33 | 37 | //#define DO_SINGLE_STEP |
34 | 38 | //#define PPC_DEBUG_DISAS |
... | ... | @@ -2785,7 +2789,7 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, |
2785 | 2789 | TranslationBlock *tb; |
2786 | 2790 | tb = ctx->tb; |
2787 | 2791 | if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) && |
2788 | - !ctx->singlestep_enabled) { | |
2792 | + likely(!ctx->singlestep_enabled)) { | |
2789 | 2793 | tcg_gen_goto_tb(n); |
2790 | 2794 | gen_set_T1(dest); |
2791 | 2795 | #if defined(TARGET_PPC64) |
... | ... | @@ -2803,8 +2807,20 @@ static always_inline void gen_goto_tb (DisasContext *ctx, int n, |
2803 | 2807 | else |
2804 | 2808 | #endif |
2805 | 2809 | gen_op_b_T1(); |
2806 | - if (ctx->singlestep_enabled) | |
2807 | - gen_op_debug(); | |
2810 | + if (unlikely(ctx->singlestep_enabled)) { | |
2811 | + if ((ctx->singlestep_enabled & | |
2812 | + (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) && | |
2813 | + ctx->exception == POWERPC_EXCP_BRANCH) { | |
2814 | + target_ulong tmp = ctx->nip; | |
2815 | + ctx->nip = dest; | |
2816 | + GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0); | |
2817 | + ctx->nip = tmp; | |
2818 | + } | |
2819 | + if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) { | |
2820 | + gen_update_nip(ctx, dest); | |
2821 | + gen_op_debug(); | |
2822 | + } | |
2823 | + } | |
2808 | 2824 | tcg_gen_exit_tb(0); |
2809 | 2825 | } |
2810 | 2826 | } |
... | ... | @@ -2824,6 +2840,7 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
2824 | 2840 | { |
2825 | 2841 | target_ulong li, target; |
2826 | 2842 | |
2843 | + ctx->exception = POWERPC_EXCP_BRANCH; | |
2827 | 2844 | /* sign extend LI */ |
2828 | 2845 | #if defined(TARGET_PPC64) |
2829 | 2846 | if (ctx->sf_mode) |
... | ... | @@ -2842,7 +2859,6 @@ GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
2842 | 2859 | if (LK(ctx->opcode)) |
2843 | 2860 | gen_setlr(ctx, ctx->nip); |
2844 | 2861 | gen_goto_tb(ctx, 0, target); |
2845 | - ctx->exception = POWERPC_EXCP_BRANCH; | |
2846 | 2862 | } |
2847 | 2863 | |
2848 | 2864 | #define BCOND_IM 0 |
... | ... | @@ -2857,6 +2873,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) |
2857 | 2873 | uint32_t bi = BI(ctx->opcode); |
2858 | 2874 | uint32_t mask; |
2859 | 2875 | |
2876 | + ctx->exception = POWERPC_EXCP_BRANCH; | |
2860 | 2877 | if ((bo & 0x4) == 0) |
2861 | 2878 | gen_op_dec_ctr(); |
2862 | 2879 | switch(type) { |
... | ... | @@ -2906,7 +2923,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) |
2906 | 2923 | case 6: |
2907 | 2924 | if (type == BCOND_IM) { |
2908 | 2925 | gen_goto_tb(ctx, 0, target); |
2909 | - goto out; | |
2926 | + return; | |
2910 | 2927 | } else { |
2911 | 2928 | #if defined(TARGET_PPC64) |
2912 | 2929 | if (ctx->sf_mode) |
... | ... | @@ -2985,12 +3002,12 @@ static always_inline void gen_bcond (DisasContext *ctx, int type) |
2985 | 3002 | #endif |
2986 | 3003 | gen_op_btest_T1(ctx->nip); |
2987 | 3004 | no_test: |
2988 | - if (ctx->singlestep_enabled) | |
3005 | + if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) { | |
3006 | + gen_update_nip(ctx, ctx->nip); | |
2989 | 3007 | gen_op_debug(); |
3008 | + } | |
2990 | 3009 | tcg_gen_exit_tb(0); |
2991 | 3010 | } |
2992 | - out: | |
2993 | - ctx->exception = POWERPC_EXCP_BRANCH; | |
2994 | 3011 | } |
2995 | 3012 | |
2996 | 3013 | GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW) |
... | ... | @@ -6150,7 +6167,6 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
6150 | 6167 | target_ulong pc_start; |
6151 | 6168 | uint16_t *gen_opc_end; |
6152 | 6169 | int supervisor, little_endian; |
6153 | - int single_step, branch_step; | |
6154 | 6170 | int j, lj = -1; |
6155 | 6171 | |
6156 | 6172 | pc_start = tb->pc; |
... | ... | @@ -6184,14 +6200,13 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
6184 | 6200 | else |
6185 | 6201 | ctx.altivec_enabled = 0; |
6186 | 6202 | if ((env->flags & POWERPC_FLAG_SE) && msr_se) |
6187 | - single_step = 1; | |
6203 | + ctx.singlestep_enabled = CPU_SINGLE_STEP; | |
6188 | 6204 | else |
6189 | - single_step = 0; | |
6205 | + ctx.singlestep_enabled = 0; | |
6190 | 6206 | if ((env->flags & POWERPC_FLAG_BE) && msr_be) |
6191 | - branch_step = 1; | |
6192 | - else | |
6193 | - branch_step = 0; | |
6194 | - ctx.singlestep_enabled = env->singlestep_enabled || single_step == 1; | |
6207 | + ctx.singlestep_enabled |= CPU_BRANCH_STEP; | |
6208 | + if (unlikely(env->singlestep_enabled)) | |
6209 | + ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP; | |
6195 | 6210 | #if defined (DO_SINGLE_STEP) && 0 |
6196 | 6211 | /* Single step trace mode */ |
6197 | 6212 | msr_se = 1; |
... | ... | @@ -6284,14 +6299,11 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
6284 | 6299 | handler->count++; |
6285 | 6300 | #endif |
6286 | 6301 | /* Check trace mode exceptions */ |
6287 | - if (unlikely(branch_step != 0 && | |
6288 | - ctx.exception == POWERPC_EXCP_BRANCH)) { | |
6289 | - GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); | |
6290 | - } else if (unlikely(single_step != 0 && | |
6291 | - (ctx.nip <= 0x100 || ctx.nip > 0xF00 || | |
6292 | - (ctx.nip & 0xFC) != 0x04) && | |
6293 | - ctx.exception != POWERPC_SYSCALL && | |
6294 | - ctx.exception != POWERPC_EXCP_TRAP)) { | |
6302 | + if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP && | |
6303 | + (ctx.nip <= 0x100 || ctx.nip > 0xF00) && | |
6304 | + ctx.exception != POWERPC_SYSCALL && | |
6305 | + ctx.exception != POWERPC_EXCP_TRAP && | |
6306 | + ctx.exception != POWERPC_EXCP_BRANCH)) { | |
6295 | 6307 | GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0); |
6296 | 6308 | } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) || |
6297 | 6309 | (env->singlestep_enabled))) { |
... | ... | @@ -6307,6 +6319,10 @@ static always_inline int gen_intermediate_code_internal (CPUState *env, |
6307 | 6319 | if (ctx.exception == POWERPC_EXCP_NONE) { |
6308 | 6320 | gen_goto_tb(&ctx, 0, ctx.nip); |
6309 | 6321 | } else if (ctx.exception != POWERPC_EXCP_BRANCH) { |
6322 | + if (unlikely(env->singlestep_enabled)) { | |
6323 | + gen_update_nip(&ctx, ctx.nip); | |
6324 | + gen_op_debug(); | |
6325 | + } | |
6310 | 6326 | /* Generate the return instruction */ |
6311 | 6327 | tcg_gen_exit_tb(0); |
6312 | 6328 | } | ... | ... |