diff options
author | Lluís Vilanova <vilanova@ac.upc.edu> | 2017-07-14 12:22:12 +0300 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2017-09-06 08:06:47 -0700 |
commit | a68956ad7f8510bdc0b54793c65c62c6a94570a4 (patch) | |
tree | 7aa551a7bfeaae1d1aaad5bbcd8890b4611f4f57 /target/arm/translate.c | |
parent | f62bd897e64c6fb1f93e8795e835980516fe53b5 (diff) | |
download | qemu-a68956ad7f8510bdc0b54793c65c62c6a94570a4.zip |
target/arm: [tcg,a64] Port to insn_start
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: Alex Benneé <alex.benee@linaro.org>
Message-Id: <150002413187.22386.156315485813606121.stgit@frigg.lan>
[rth: Use DISAS_TOO_MANY for "execute only one more" after bp.]
Signed-off-by: Richard Henderson <rth@twiddle.net>
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 005157225c..2f5f65310d 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 |