mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2024-12-23 17:25:27 +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 */
|
/* 0x08 currently unused */
|
||||||
#define BP_GDB 0x10
|
#define BP_GDB 0x10
|
||||||
#define BP_CPU 0x20
|
#define BP_CPU 0x20
|
||||||
|
#define BP_ANY (BP_GDB | BP_CPU)
|
||||||
#define BP_WATCHPOINT_HIT_READ 0x40
|
#define BP_WATCHPOINT_HIT_READ 0x40
|
||||||
#define BP_WATCHPOINT_HIT_WRITE 0x80
|
#define BP_WATCHPOINT_HIT_WRITE 0x80
|
||||||
#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE)
|
#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_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint);
|
||||||
void cpu_watchpoint_remove_all(CPUState *cpu, int mask);
|
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, ...)
|
void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||||
GCC_FMT_ATTR(2, 3);
|
GCC_FMT_ATTR(2, 3);
|
||||||
|
|
||||||
|
|
|
@ -11216,7 +11216,6 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
DisasContext dc1, *dc = &dc1;
|
DisasContext dc1, *dc = &dc1;
|
||||||
CPUBreakpoint *bp;
|
|
||||||
target_ulong pc_start;
|
target_ulong pc_start;
|
||||||
target_ulong next_page_start;
|
target_ulong next_page_start;
|
||||||
int num_insns;
|
int num_insns;
|
||||||
|
@ -11316,28 +11315,22 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
tcg_gen_insn_start(tcg_ctx, dc->pc, 0);
|
||||||
|
num_insns++;
|
||||||
|
|
||||||
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
||||||
|
CPUBreakpoint *bp;
|
||||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||||
if (bp->pc == dc->pc) {
|
if (bp->pc == dc->pc) {
|
||||||
if (bp->flags & BP_CPU) {
|
gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
|
||||||
gen_helper_check_breakpoints(tcg_ctx, tcg_ctx->cpu_env);
|
/* Advance PC so that clearing the breakpoint will
|
||||||
/* End the TB early; it likely won't be executed */
|
invalidate this TB. */
|
||||||
dc->is_jmp = DISAS_UPDATE;
|
dc->pc += 2;
|
||||||
} else {
|
goto done_generating;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_gen_insn_start(tcg_ctx, dc->pc, 0);
|
|
||||||
num_insns++;
|
|
||||||
|
|
||||||
//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();
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -11386,7 +11386,6 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||||
ARMCPU *cpu = arm_env_get_cpu(env);
|
ARMCPU *cpu = arm_env_get_cpu(env);
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
DisasContext dc1, *dc = &dc1;
|
DisasContext dc1, *dc = &dc1;
|
||||||
CPUBreakpoint *bp;
|
|
||||||
target_ulong pc_start;
|
target_ulong pc_start;
|
||||||
target_ulong next_page_start;
|
target_ulong next_page_start;
|
||||||
int num_insns;
|
int num_insns;
|
||||||
|
@ -11541,7 +11540,9 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||||
store_cpu_field(tcg_ctx, tmp, condexec_bits);
|
store_cpu_field(tcg_ctx, tmp, condexec_bits);
|
||||||
}
|
}
|
||||||
do {
|
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
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* Intercept jump to the magic kernel page. */
|
/* Intercept jump to the magic kernel page. */
|
||||||
if (dc->pc >= 0xffff0000) {
|
if (dc->pc >= 0xffff0000) {
|
||||||
|
@ -11562,6 +11563,7 @@ void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
|
||||||
|
CPUBreakpoint *bp;
|
||||||
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
|
||||||
if (bp->pc == dc->pc) {
|
if (bp->pc == dc->pc) {
|
||||||
if (bp->flags & BP_CPU) {
|
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)) {
|
//if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
|
||||||
// gen_io_start();
|
// gen_io_start();
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -8567,7 +8567,6 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
DisasContext dc1, *dc = &dc1;
|
DisasContext dc1, *dc = &dc1;
|
||||||
target_ulong pc_ptr;
|
target_ulong pc_ptr;
|
||||||
CPUBreakpoint *bp;
|
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
target_ulong pc_start;
|
target_ulong pc_start;
|
||||||
target_ulong cs_base;
|
target_ulong cs_base;
|
||||||
|
@ -8701,18 +8700,17 @@ void gen_intermediate_code(CPUX86State *env, TranslationBlock *tb)
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
for(;;) {
|
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);
|
tcg_gen_insn_start(tcg_ctx, pc_start, dc->cc_op);
|
||||||
num_insns++;
|
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)) {
|
//if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
|
||||||
// gen_io_start();
|
// gen_io_start();
|
||||||
//}
|
//}
|
||||||
|
|
|
@ -3059,7 +3059,6 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
|
||||||
M68kCPU *cpu = m68k_env_get_cpu(env);
|
M68kCPU *cpu = m68k_env_get_cpu(env);
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
DisasContext dc1, *dc = &dc1;
|
DisasContext dc1, *dc = &dc1;
|
||||||
CPUBreakpoint *bp;
|
|
||||||
target_ulong pc_start;
|
target_ulong pc_start;
|
||||||
int pc_offset;
|
int pc_offset;
|
||||||
int num_insns;
|
int num_insns;
|
||||||
|
@ -3112,20 +3111,15 @@ void gen_intermediate_code(CPUM68KState *env, TranslationBlock *tb)
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
do {
|
do {
|
||||||
pc_offset = dc->pc - pc_start;
|
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);
|
tcg_gen_insn_start(tcg_ctx, dc->pc);
|
||||||
num_insns++;
|
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
|
// UNICORN: Commented out
|
||||||
//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();
|
||||||
|
|
|
@ -19701,7 +19701,6 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
|
||||||
DisasContext ctx;
|
DisasContext ctx;
|
||||||
target_ulong pc_start;
|
target_ulong pc_start;
|
||||||
target_ulong next_page_start;
|
target_ulong next_page_start;
|
||||||
CPUBreakpoint *bp;
|
|
||||||
int num_insns;
|
int num_insns;
|
||||||
int max_insns;
|
int max_insns;
|
||||||
int insn_bytes;
|
int insn_bytes;
|
||||||
|
@ -19773,24 +19772,19 @@ void gen_intermediate_code(CPUMIPSState *env, struct TranslationBlock *tb)
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
while (ctx.bstate == BS_NONE) {
|
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);
|
tcg_gen_insn_start(tcg_ctx, ctx.pc, ctx.hflags & MIPS_HFLAG_BMASK, ctx.btarget);
|
||||||
num_insns++;
|
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
|
// Unicorn: Commented out
|
||||||
//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();
|
||||||
|
|
|
@ -5363,7 +5363,6 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
target_ulong pc_start, last_pc;
|
target_ulong pc_start, last_pc;
|
||||||
DisasContext dc1, *dc = &dc1;
|
DisasContext dc1, *dc = &dc1;
|
||||||
CPUBreakpoint *bp;
|
|
||||||
int num_insns = 0;
|
int num_insns = 0;
|
||||||
int max_insns;
|
int max_insns;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
|
@ -5419,18 +5418,6 @@ void gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
|
||||||
|
|
||||||
gen_tb_start(tcg_ctx);
|
gen_tb_start(tcg_ctx);
|
||||||
do {
|
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) {
|
if (dc->npc & JUMP_PC) {
|
||||||
assert(dc->jump_pc[1] == dc->pc + 4);
|
assert(dc->jump_pc[1] == dc->pc + 4);
|
||||||
tcg_gen_insn_start(tcg_ctx, dc->pc, dc->jump_pc[0] | JUMP_PC);
|
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++;
|
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)) {
|
//if (num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
|
||||||
// gen_io_start();
|
// gen_io_start();
|
||||||
//}
|
//}
|
||||||
|
|
Loading…
Reference in a new issue