@@ -11267,6 +11267,29 @@ static void aarch64_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
tcg_gen_insn_start(dc->pc, 0, 0);
}
+static BreakpointCheckType aarch64_trblock_breakpoint_check(
+ DisasContextBase *db, CPUState *cpu, const CPUBreakpoint *bp)
+{
+ DisasContext *dc = container_of(db, DisasContext, base);
+
+ if (bp->flags & BP_CPU) {
+ gen_a64_set_pc_im(dc->pc);
+ gen_helper_check_breakpoints(cpu_env);
+ /* End the TB early; it likely won't be executed */
+ db->is_jmp = DJ_UPDATE;
+ return BC_HIT_INSN;
+ } 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. */
+ dc->pc += 4;
+ return BC_HIT_TB;
+ }
+}
+
void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
TranslationBlock *tb)
{
@@ -11275,6 +11298,7 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
DisasContext *dc = container_of(db, DisasContext, base);
target_ulong next_page_start;
int max_insns;
+ CPUBreakpoint *bp;
db->tb = tb;
db->pc_first = tb->pc;
@@ -11301,29 +11325,24 @@ void gen_intermediate_code_a64(DisasContextBase *db, ARMCPU *cpu,
db->num_insns++;
aarch64_trblock_insn_start(db, cs);
- 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_a64_set_pc_im(dc->pc);
- gen_helper_check_breakpoints(cpu_env);
- /* End the TB early; it likely won't be executed */
- db->is_jmp = DJ_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. */
- dc->pc += 4;
- goto done_generating;
- }
+ bp = NULL;
+ do {
+ bp = cpu_breakpoint_get(cs, db->pc_next, bp);
+ if (unlikely(bp)) {
+ BreakpointCheckType bp_check =
+ aarch64_trblock_breakpoint_check(db, cs, bp);
+ if (bp_check == BC_HIT_INSN) {
+ /* Hit, keep translating */
+ /*
+ * TODO: if we're never going to have more than one BP in a
+ * single address, we can simply use a bool here.
+ */
break;
+ } else {
+ goto done_generating;
}
}
- }
+ } while (bp != NULL);
if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start(cpu_env);
@@ -11954,6 +11954,33 @@ static void arm_trblock_insn_start(DisasContextBase *db, CPUState *cpu)
#endif
}
+static BreakpointCheckType arm_trblock_breakpoint_check(DisasContextBase *db,
+ CPUState *cpu,
+ const CPUBreakpoint *bp)
+{
+ DisasContext *dc = container_of(db, 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 */
+ db->is_jmp = DJ_UPDATE;
+ return BC_HIT_INSN;
+ } 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;
+ return BC_HIT_TB;
+ }
+}
+
/* generate intermediate code for basic block 'tb'. */
void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
{
@@ -11964,6 +11991,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
target_ulong next_page_start;
int max_insns;
bool end_of_page;
+ CPUBreakpoint *bp;
/* generate intermediate code */
@@ -12003,32 +12031,24 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
db->num_insns++;
arm_trblock_insn_start(db, cpu);
- if (unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
- CPUBreakpoint *bp;
- QTAILQ_FOREACH(bp, &cpu->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 */
- db->is_jmp = DJ_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;
- }
+ bp = NULL;
+ do {
+ bp = cpu_breakpoint_get(cpu, db->pc_next, bp);
+ if (unlikely(bp)) {
+ BreakpointCheckType bp_check = arm_trblock_breakpoint_check(
+ db, cpu, bp);
+ if (bp_check == BC_HIT_INSN) {
+ /* Hit, keep translating */
+ /*
+ * TODO: if we're never going to have more than one BP in a
+ * single address, we can simply use a bool here.
+ */
break;
+ } else {
+ goto done_generating;
}
}
- }
+ } while (bp != NULL);
if (db->num_insns == max_insns && (tb->cflags & CF_LAST_IO)) {
gen_io_start(cpu_env);
Incrementally paves the way towards using the generic instruction translation loop. Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu> --- target/arm/translate-a64.c | 59 ++++++++++++++++++++++++++------------- target/arm/translate.c | 66 +++++++++++++++++++++++++++++--------------- 2 files changed, 82 insertions(+), 43 deletions(-)