Skip to content

Commit

Permalink
target-*: Introduce and use cpu_breakpoint_test
Browse files Browse the repository at this point in the history
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.

Reviewed-by: Aurelien Jarno <[email protected]>
Reviewed-by: Peter Maydell <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
  • Loading branch information
rth7680 committed Oct 7, 2015
1 parent 959082f commit b933066
Show file tree
Hide file tree
Showing 18 changed files with 160 additions and 239 deletions.
16 changes: 16 additions & 0 deletions include/qom/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,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)
Expand All @@ -731,6 +732,21 @@ int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags);
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint);
void cpu_breakpoint_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;
}

int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
int flags, CPUWatchpoint **watchpoint);
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
Expand Down
13 changes: 4 additions & 9 deletions target-alpha/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2868,7 +2868,6 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
target_ulong pc_start;
target_ulong pc_mask;
uint32_t insn;
CPUBreakpoint *bp;
int j, lj = -1;
ExitStatus ret;
int num_insns;
Expand Down Expand Up @@ -2913,14 +2912,6 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,

gen_tb_start(tb);
do {
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == ctx.pc) {
gen_excp(&ctx, EXCP_DEBUG, 0);
break;
}
}
}
if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -2936,6 +2927,10 @@ static inline void gen_intermediate_code_internal(AlphaCPU *cpu,
tcg_gen_insn_start(ctx.pc);
num_insns++;

if (unlikely(cpu_breakpoint_test(cs, ctx.pc, BP_ANY))) {
gen_excp(&ctx, EXCP_DEBUG, 0);
break;
}
if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
Expand Down
26 changes: 13 additions & 13 deletions target-arm/translate-a64.c
Original file line number Diff line number Diff line change
Expand Up @@ -11007,7 +11007,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
CPUState *cs = CPU(cpu);
CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp;
int j, lj;
target_ulong pc_start;
target_ulong next_page_start;
Expand Down Expand Up @@ -11079,18 +11078,6 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
tcg_clear_temp_count();

do {
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
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;
}
}
}

if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -11106,6 +11093,19 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu,
tcg_gen_insn_start(dc->pc);
num_insns++;

if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
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;
}
}
}

if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
Expand Down
31 changes: 16 additions & 15 deletions target-arm/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -11177,7 +11177,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
CPUState *cs = CPU(cpu);
CPUARMState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp;
int j, lj;
target_ulong pc_start;
target_ulong next_page_start;
Expand Down Expand Up @@ -11306,6 +11305,21 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
store_cpu_field(tmp, condexec_bits);
}
do {
if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
lj++;
while (lj < j)
tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
tcg_ctx.gen_opc_pc[lj] = dc->pc;
gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
tcg_ctx.gen_opc_instr_start[lj] = 1;
tcg_ctx.gen_opc_icount[lj] = num_insns;
}
tcg_gen_insn_start(dc->pc);
num_insns++;

#ifdef CONFIG_USER_ONLY
/* Intercept jump to the magic kernel page. */
if (dc->pc >= 0xffff0000) {
Expand All @@ -11326,6 +11340,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
#endif

if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
CPUBreakpoint *bp;
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
Expand All @@ -11336,20 +11351,6 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu,
}
}
}
if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
lj++;
while (lj < j)
tcg_ctx.gen_opc_instr_start[lj++] = 0;
}
tcg_ctx.gen_opc_pc[lj] = dc->pc;
gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
tcg_ctx.gen_opc_instr_start[lj] = 1;
tcg_ctx.gen_opc_icount[lj] = num_insns;
}
tcg_gen_insn_start(dc->pc);
num_insns++;

if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
Expand Down
27 changes: 8 additions & 19 deletions target-cris/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -3030,23 +3030,6 @@ static unsigned int crisv32_decoder(CPUCRISState *env, DisasContext *dc)
return insn_len;
}

static void check_breakpoint(CPUCRISState *env, DisasContext *dc)
{
CPUState *cs = CPU(cris_env_get_cpu(env));
CPUBreakpoint *bp;

if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
cris_evaluate_flags(dc);
tcg_gen_movi_tl(env_pc, dc->pc);
t_gen_raise_exception(EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
}
}
}
}

#include "translate_v10.c"

/*
Expand Down Expand Up @@ -3175,8 +3158,6 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,

gen_tb_start(tb);
do {
check_breakpoint(env, dc);

if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -3196,6 +3177,14 @@ gen_intermediate_code_internal(CRISCPU *cpu, TranslationBlock *tb,
tcg_gen_insn_start(dc->pc);
num_insns++;

if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
cris_evaluate_flags(dc);
tcg_gen_movi_tl(env_pc, dc->pc);
t_gen_raise_exception(EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
break;
}

/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);

Expand Down
17 changes: 7 additions & 10 deletions target-i386/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -7849,7 +7849,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
CPUX86State *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
target_ulong pc_ptr;
CPUBreakpoint *bp;
int j, lj;
uint64_t flags;
target_ulong pc_start;
Expand Down Expand Up @@ -7938,15 +7937,6 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,

gen_tb_start(tb);
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;
}
}
}
if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -7962,6 +7952,13 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
tcg_gen_insn_start(pc_ptr);
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;
}
if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
Expand Down
25 changes: 7 additions & 18 deletions target-lm32/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,22 +1032,6 @@ static inline void decode(DisasContext *dc, uint32_t ir)
decinfo[dc->opcode](dc);
}

static void check_breakpoint(CPULM32State *env, DisasContext *dc)
{
CPUState *cs = CPU(lm32_env_get_cpu(env));
CPUBreakpoint *bp;

if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
t_gen_raise_exception(dc, EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
}
}
}
}

/* generate intermediate code for basic block 'tb'. */
static inline
void gen_intermediate_code_internal(LM32CPU *cpu,
Expand Down Expand Up @@ -1088,8 +1072,6 @@ void gen_intermediate_code_internal(LM32CPU *cpu,

gen_tb_start(tb);
do {
check_breakpoint(env, dc);

if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -1105,6 +1087,13 @@ void gen_intermediate_code_internal(LM32CPU *cpu,
tcg_gen_insn_start(dc->pc);
num_insns++;

if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
tcg_gen_movi_tl(cpu_pc, dc->pc);
t_gen_raise_exception(dc, EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
break;
}

/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);

Expand Down
18 changes: 6 additions & 12 deletions target-m68k/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -2969,7 +2969,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
CPUState *cs = CPU(cpu);
CPUM68KState *env = &cpu->env;
DisasContext dc1, *dc = &dc1;
CPUBreakpoint *bp;
int j, lj;
target_ulong pc_start;
int pc_offset;
Expand Down Expand Up @@ -2999,17 +2998,6 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
do {
pc_offset = dc->pc - pc_start;
gen_throws_exception = NULL;
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;
}
if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -3024,6 +3012,12 @@ gen_intermediate_code_internal(M68kCPU *cpu, TranslationBlock *tb,
tcg_gen_insn_start(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;
}

if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start();
}
Expand Down
36 changes: 13 additions & 23 deletions target-microblaze/translate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1626,21 +1626,6 @@ static inline void decode(DisasContext *dc, uint32_t ir)
}
}

static void check_breakpoint(CPUMBState *env, DisasContext *dc)
{
CPUState *cs = CPU(mb_env_get_cpu(env));
CPUBreakpoint *bp;

if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
t_gen_raise_exception(dc, EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
}
}
}
}

/* generate intermediate code for basic block 'tb'. */
static inline void
gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
Expand Down Expand Up @@ -1695,14 +1680,6 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
gen_tb_start(tb);
do
{
#if SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_debug();
}
#endif
check_breakpoint(env, dc);

if (search_pc) {
j = tcg_op_buf_count();
if (lj < j) {
Expand All @@ -1717,6 +1694,19 @@ gen_intermediate_code_internal(MicroBlazeCPU *cpu, TranslationBlock *tb,
tcg_gen_insn_start(dc->pc);
num_insns++;

#if SIM_COMPAT
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
tcg_gen_movi_tl(cpu_SR[SR_PC], dc->pc);
gen_helper_debug();
}
#endif

if (unlikely(cpu_breakpoint_test(cs, dc->pc, BP_ANY))) {
t_gen_raise_exception(dc, EXCP_DEBUG);
dc->is_jmp = DISAS_UPDATE;
break;
}

/* Pretty disas. */
LOG_DIS("%8.8x:\t", dc->pc);

Expand Down
Loading

0 comments on commit b933066

Please sign in to comment.