From 3ec0adcc07b7ec8136e8cffa4d815e88cdac7fe9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 17 Feb 2018 14:02:36 -0500 Subject: [PATCH] target-*: Introduce and use cpu_breakpoint_test Reduce the boilerplate required for each target. At the same time, move the test for breakpoint after calling tcg_gen_insn_start. Note that arm and aarch64 do not use cpu_breakpoint_test, but still move the inline test down after tcg_gen_insn_start. Backports commit b933066ae03d924a92b2616b4a24e7d91cd5b841 from qemu --- qemu/include/qom/cpu.h | 16 ++++++++++++++++ qemu/target-arm/translate-a64.c | 25 +++++++++---------------- qemu/target-arm/translate.c | 10 ++++------ qemu/target-i386/translate.c | 18 ++++++++---------- qemu/target-m68k/translate.c | 18 ++++++------------ qemu/target-mips/translate.c | 26 ++++++++++---------------- qemu/target-sparc/translate.c | 23 ++++++++++------------- 7 files changed, 63 insertions(+), 73 deletions(-) diff --git a/qemu/include/qom/cpu.h b/qemu/include/qom/cpu.h index 4c71c834..a67b4041 100644 --- a/qemu/include/qom/cpu.h +++ b/qemu/include/qom/cpu.h @@ -612,6 +612,7 @@ void cpu_single_step(CPUState *cpu, int enabled); /* 0x08 currently unused */ #define BP_GDB 0x10 #define BP_CPU 0x20 +#define BP_ANY (BP_GDB | BP_CPU) #define BP_WATCHPOINT_HIT_READ 0x40 #define BP_WATCHPOINT_HIT_WRITE 0x80 #define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE) @@ -629,6 +630,21 @@ int cpu_watchpoint_remove(CPUState *cpu, vaddr addr, void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint); void cpu_watchpoint_remove_all(CPUState *cpu, int mask); +/* Return true if PC matches an installed breakpoint. */ +static inline bool cpu_breakpoint_test(CPUState *cpu, vaddr pc, int mask) +{ + CPUBreakpoint *bp; + + if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) { + QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { + if (bp->pc == pc && (bp->flags & mask)) { + return true; + } + } + } + return false; +} + void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...) GCC_FMT_ATTR(2, 3); diff --git a/qemu/target-arm/translate-a64.c b/qemu/target-arm/translate-a64.c index 93f1a66a..18ccb366 100644 --- a/qemu/target-arm/translate-a64.c +++ b/qemu/target-arm/translate-a64.c @@ -11216,7 +11216,6 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb) CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; target_ulong pc_start; target_ulong next_page_start; int num_insns; @@ -11316,28 +11315,22 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb) gen_tb_start(tcg_ctx); do { + tcg_gen_insn_start(tcg_ctx, dc->pc, 0); + num_insns++; + if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { + CPUBreakpoint *bp; QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { if (bp->pc == dc->pc) { - if (bp->flags & BP_CPU) { - gen_helper_check_breakpoints(tcg_ctx, tcg_ctx->cpu_env); - /* End the TB early; it likely won't be executed */ - dc->is_jmp = DISAS_UPDATE; - } else { - gen_exception_internal_insn(dc, 0, EXCP_DEBUG); - /* Advance PC so that clearing the breakpoint will - invalidate this TB. */ - dc->pc += 4; - goto done_generating; - } - break; + gen_exception_internal_insn(dc, 0, EXCP_DEBUG); + /* Advance PC so that clearing the breakpoint will + invalidate this TB. */ + dc->pc += 2; + goto done_generating; } } } - tcg_gen_insn_start(tcg_ctx, dc->pc, 0); - num_insns++; - //if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { // gen_io_start(); //} diff --git a/qemu/target-arm/translate.c b/qemu/target-arm/translate.c index 65efb4b1..9195dfb5 100644 --- a/qemu/target-arm/translate.c +++ b/qemu/target-arm/translate.c @@ -11386,7 +11386,6 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) ARMCPU *cpu = arm_env_get_cpu(env); CPUState *cs = CPU(cpu); DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; target_ulong pc_start; target_ulong next_page_start; int num_insns; @@ -11541,7 +11540,9 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) store_cpu_field(tcg_ctx, tmp, condexec_bits); } do { - //printf(">>> arm pc = %x\n", dc->pc); + tcg_gen_insn_start(tcg_ctx, dc->pc, + (dc->condexec_cond << 4) | (dc->condexec_mask >> 1)); + num_insns++; #ifdef CONFIG_USER_ONLY /* Intercept jump to the magic kernel page. */ if (dc->pc >= 0xffff0000) { @@ -11562,6 +11563,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) #endif if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { + CPUBreakpoint *bp; QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { if (bp->pc == dc->pc) { if (bp->flags & BP_CPU) { @@ -11582,10 +11584,6 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb) } } - tcg_gen_insn_start(tcg_ctx, dc->pc, - (dc->condexec_cond << 4) | (dc->condexec_mask >> 1)); - num_insns++; - //if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { // gen_io_start(); //} diff --git a/qemu/target-i386/translate.c b/qemu/target-i386/translate.c index c25fcd48..9028138e 100644 --- a/qemu/target-i386/translate.c +++ b/qemu/target-i386/translate.c @@ -8567,7 +8567,6 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) TCGContext *tcg_ctx = env->uc->tcg_ctx; DisasContext dc1, *dc = &dc1; target_ulong pc_ptr; - CPUBreakpoint *bp; uint64_t flags; target_ulong pc_start; target_ulong cs_base; @@ -8701,18 +8700,17 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb) gen_tb_start(tcg_ctx); for(;;) { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == pc_ptr && - !((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) { - gen_debug(dc, pc_ptr - dc->cs_base); - goto done_generating; - } - } - } tcg_gen_insn_start(tcg_ctx, pc_start, dc->cc_op); num_insns++; + /* If RF is set, suppress an internally generated breakpoint. */ + if (unlikely(cpu_breakpoint_test(cs, pc_ptr, + tb->flags & HF_RF_MASK + ? BP_GDB : BP_ANY))) { + gen_debug(dc, pc_ptr - dc->cs_base); + goto done_generating; + } + // Unicorn: commented out //if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { // gen_io_start(); //} diff --git a/qemu/target-m68k/translate.c b/qemu/target-m68k/translate.c index e68e1535..4a2110e9 100644 --- a/qemu/target-m68k/translate.c +++ b/qemu/target-m68k/translate.c @@ -3059,7 +3059,6 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb) M68kCPU *cpu = m68k_env_get_cpu(env); CPUState *cs = CPU(cpu); DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; target_ulong pc_start; int pc_offset; int num_insns; @@ -3112,20 +3111,15 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb) gen_tb_start(tcg_ctx); do { pc_offset = dc->pc - pc_start; - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - gen_exception(dc, dc->pc, EXCP_DEBUG); - dc->is_jmp = DISAS_JUMP; - break; - } - } - if (dc->is_jmp) - break; - } tcg_gen_insn_start(tcg_ctx, dc->pc); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + gen_exception(dc, dc->pc, EXCP_DEBUG); + dc->is_jmp = DISAS_JUMP; + break; + } + // UNICORN: Commented out //if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { // gen_io_start(); diff --git a/qemu/target-mips/translate.c b/qemu/target-mips/translate.c index 493b3f88..12b74400 100644 --- a/qemu/target-mips/translate.c +++ b/qemu/target-mips/translate.c @@ -19701,7 +19701,6 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb) DisasContext ctx; target_ulong pc_start; target_ulong next_page_start; - CPUBreakpoint *bp; int num_insns; int max_insns; int insn_bytes; @@ -19773,24 +19772,19 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb) gen_tb_start(tcg_ctx); while (ctx.bstate == BS_NONE) { - // printf(">>> mips pc = %x\n", ctx.pc); - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == ctx.pc) { - save_cpu_state(&ctx, 1); - ctx.bstate = BS_BRANCH; - gen_helper_raise_exception_debug(tcg_ctx, tcg_ctx->cpu_env); - /* Include the breakpoint location or the tb won't - * be flushed when it must be. */ - ctx.pc += 4; - goto done_generating; - } - } - } - tcg_gen_insn_start(tcg_ctx, ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget); num_insns++; + if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) { + save_cpu_state(&ctx, 1); + ctx.bstate = BS_BRANCH; + gen_helper_raise_exception_debug(tcg_ctx, tcg_ctx->cpu_env); + /* Include the breakpoint location or the tb won't + * be flushed when it must be. */ + ctx.pc += 4; + goto done_generating; + } + // Unicorn: Commented out //if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { // gen_io_start(); diff --git a/qemu/target-sparc/translate.c b/qemu/target-sparc/translate.c index af2a3062..51824750 100644 --- a/qemu/target-sparc/translate.c +++ b/qemu/target-sparc/translate.c @@ -5363,7 +5363,6 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) CPUState *cs = CPU(cpu); target_ulong pc_start, last_pc; DisasContext dc1, *dc = &dc1; - CPUBreakpoint *bp; int num_insns = 0; int max_insns; unsigned int insn; @@ -5419,18 +5418,6 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) gen_tb_start(tcg_ctx); do { - if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) { - QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - if (bp->pc == dc->pc) { - if (dc->pc != pc_start) - save_state(dc); - gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env); - tcg_gen_exit_tb(tcg_ctx, 0); - dc->is_br = 1; - goto exit_gen_loop; - } - } - } if (dc->npc & JUMP_PC) { assert(dc->jump_pc[1] == dc->pc + 4); tcg_gen_insn_start(tcg_ctx, dc->pc, dc->jump_pc[0] | JUMP_PC); @@ -5439,6 +5426,16 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb) } num_insns++; + if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) { + if (dc->pc != pc_start) { + save_state(dc); + } + gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env); + tcg_gen_exit_tb(tcg_ctx, 0); + dc->is_br = 1; + goto exit_gen_loop; + } + //if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { // gen_io_start(); //}