diff options
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 55 |
1 files changed, 35 insertions, 20 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index 0051572..2f5f653 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -11946,6 +11946,33 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) 0); } +static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu, + const CPUBreakpoint *bp) +{ + DisasContext *dc = container_of(dcbase, DisasContext, base); + + if (bp->flags & BP_CPU) { + gen_set_condexec(dc); + gen_set_pc_im(dc, dc->pc); + gen_helper_check_breakpoints(cpu_env); + /* End the TB early; it's likely not going to be executed */ + dc->base.is_jmp = DISAS_TOO_MANY; + } else { + gen_exception_internal_insn(dc, 0, EXCP_DEBUG); + /* 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. */ + /* TODO: Advance PC by correct instruction length to + * avoid disassembler error messages */ + dc->pc += 2; + dc->base.is_jmp = DISAS_NORETURN; + } + + return true; +} + /* generate intermediate code for basic block 'tb'. */ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) { @@ -11994,28 +12021,15 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) 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_set_condexec(dc); - gen_set_pc_im(dc, dc->pc); - gen_helper_check_breakpoints(cpu_env); - /* End the TB early; it's likely not going to be executed */ - dc->base.is_jmp = DISAS_UPDATE; - } else { - gen_exception_internal_insn(dc, 0, EXCP_DEBUG); - /* 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. */ - /* TODO: Advance PC by correct instruction length to - * avoid disassembler error messages */ - dc->pc += 2; - goto done_generating; + if (bp->pc == dc->base.pc_next) { + if (arm_tr_breakpoint_check(&dc->base, cs, bp)) { + break; } - break; } } + if (dc->base.is_jmp > DISAS_TOO_MANY) { + break; + } } if (dc->base.num_insns == max_insns && (tb->cflags & CF_LAST_IO)) { @@ -12137,6 +12151,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) gen_exception(EXCP_SMC, syn_aa32_smc(), 3); break; case DISAS_NEXT: + case DISAS_TOO_MANY: case DISAS_UPDATE: gen_set_pc_im(dc, dc->pc); /* fall through */ @@ -12158,6 +12173,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) */ switch(dc->base.is_jmp) { case DISAS_NEXT: + case DISAS_TOO_MANY: gen_goto_tb(dc, 1, dc->pc); break; case DISAS_JUMP: @@ -12211,7 +12227,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb) } } -done_generating: gen_tb_end(tb, dc->base.num_insns); #ifdef DEBUG_DISAS |