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
This commit is contained in:
Richard Henderson 2018-02-17 14:02:36 -05:00 committed by Lioncash
parent 67f13016b3
commit 3ec0adcc07
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
7 changed files with 63 additions and 73 deletions

View file

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

View file

@ -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,27 +11315,21 @@ 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;
dc->pc += 2;
goto done_generating;
}
break;
}
}
}
tcg_gen_insn_start(tcg_ctx, dc->pc, 0);
num_insns++;
//if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
// gen_io_start();

View file

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

View file

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

View file

@ -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,19 +3111,14 @@ 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) {
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;
}
}
if (dc->is_jmp)
break;
}
tcg_gen_insn_start(tcg_ctx, dc->pc);
num_insns++;
// UNICORN: Commented out
//if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {

View file

@ -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,10 +19772,10 @@ 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) {
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);
@ -19785,11 +19784,6 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
ctx.pc += 4;
goto done_generating;
}
}
}
tcg_gen_insn_start(tcg_ctx, ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
num_insns++;
// Unicorn: Commented out
//if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {

View file

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