target/i386: [tcg] Port to breakpoint_check

Incrementally paves the way towards using the generic instruction translation
loop.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Emilio G. Cota <cota@braap.org>
Message-Id: <150002170871.22386.2172835658104140576.stgit@frigg.lan>
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
Lluís Vilanova 2017-07-14 11:41:48 +03:00 committed by Richard Henderson
parent 9d75f52b34
commit e6b41ec37f

View File

@ -8456,6 +8456,26 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
} }
static bool i386_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
const CPUBreakpoint *bp)
{
DisasContext *dc = container_of(dcbase, DisasContext, base);
/* If RF is set, suppress an internally generated breakpoint. */
int flags = dc->base.tb->flags & HF_RF_MASK ? BP_GDB : BP_ANY;
if (bp->flags & flags) {
gen_debug(dc, dc->base.pc_next - dc->cs_base);
dc->base.is_jmp = DISAS_NORETURN;
/* The address covered by the breakpoint must be included in
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
the logic setting tb->size below does the right thing. */
dc->base.pc_next += 1;
return true;
} else {
return false;
}
}
/* generate intermediate code for basic block 'tb'. */ /* generate intermediate code for basic block 'tb'. */
void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
{ {
@ -8486,18 +8506,21 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
i386_tr_insn_start(&dc->base, cs); i386_tr_insn_start(&dc->base, cs);
num_insns++; num_insns++;
/* If RF is set, suppress an internally generated breakpoint. */ if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
if (unlikely(cpu_breakpoint_test(cs, dc->base.pc_next, CPUBreakpoint *bp;
tb->flags & HF_RF_MASK QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
? BP_GDB : BP_ANY))) { if (bp->pc == dc->base.pc_next) {
gen_debug(dc, dc->base.pc_next - dc->cs_base); if (i386_tr_breakpoint_check(&dc->base, cs, bp)) {
/* The address covered by the breakpoint must be included in break;
[tb->pc, tb->pc + tb->size) in order to for it to be
properly cleared -- thus we increment the PC here so that
the logic setting tb->size below does the right thing. */
dc->base.pc_next += 1;
goto done_generating;
} }
}
}
if (dc->base.is_jmp == DISAS_NORETURN) {
break;
}
}
if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start(); gen_io_start();
} }
@ -8548,7 +8571,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
} }
if (tb->cflags & CF_LAST_IO) if (tb->cflags & CF_LAST_IO)
gen_io_end(); gen_io_end();
done_generating:
gen_tb_end(tb, num_insns); gen_tb_end(tb, num_insns);
#ifdef DEBUG_DISAS #ifdef DEBUG_DISAS