mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 12:35:36 +00:00
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:
parent
67f13016b3
commit
3ec0adcc07
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
//}
|
||||
|
|
|
@ -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();
|
||||
//}
|
||||
|
|
|
@ -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();
|
||||
//}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
//}
|
||||
|
|
Loading…
Reference in a new issue