1
2
3
4
5
6
7
8
9
10#include "qemu/osdep.h"
11#include "qemu/error-report.h"
12#include "cpu.h"
13#include "tcg/tcg.h"
14#include "tcg/tcg-op.h"
15#include "exec/exec-all.h"
16#include "exec/gen-icount.h"
17#include "exec/log.h"
18#include "exec/translator.h"
19#include "exec/plugin-gen.h"
20
21
22
23
24
25
26void translator_loop_temp_check(DisasContextBase *db)
27{
28 if (tcg_check_temp_count()) {
29 qemu_log("warning: TCG temporary leaks before "
30 TARGET_FMT_lx "\n", db->pc_next);
31 }
32}
33
34void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
35 CPUState *cpu, TranslationBlock *tb, int max_insns)
36{
37 int bp_insn = 0;
38 bool plugin_enabled;
39
40
41 db->tb = tb;
42 db->pc_first = tb->pc;
43 db->pc_next = db->pc_first;
44 db->is_jmp = DISAS_NEXT;
45 db->num_insns = 0;
46 db->max_insns = max_insns;
47 db->singlestep_enabled = cpu->singlestep_enabled;
48
49 ops->init_disas_context(db, cpu);
50 tcg_debug_assert(db->is_jmp == DISAS_NEXT);
51
52
53 tcg_clear_temp_count();
54
55
56 gen_tb_start(db->tb);
57 ops->tb_start(db, cpu);
58 tcg_debug_assert(db->is_jmp == DISAS_NEXT);
59
60 plugin_enabled = plugin_gen_tb_start(cpu, tb);
61
62 while (true) {
63 db->num_insns++;
64 ops->insn_start(db, cpu);
65 tcg_debug_assert(db->is_jmp == DISAS_NEXT);
66
67 if (plugin_enabled) {
68 plugin_gen_insn_start(cpu, db);
69 }
70
71
72 if (!db->singlestep_enabled
73 && unlikely(!QTAILQ_EMPTY(&cpu->breakpoints))) {
74 CPUBreakpoint *bp;
75 QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) {
76 if (bp->pc == db->pc_next) {
77 if (ops->breakpoint_check(db, cpu, bp)) {
78 bp_insn = 1;
79 break;
80 }
81 }
82 }
83
84
85
86
87 if (db->is_jmp > DISAS_TOO_MANY) {
88 break;
89 }
90 }
91
92
93
94
95
96 if (db->num_insns == db->max_insns
97 && (tb_cflags(db->tb) & CF_LAST_IO)) {
98
99 gen_io_start();
100 ops->translate_insn(db, cpu);
101 } else {
102 ops->translate_insn(db, cpu);
103 }
104
105
106 if (db->is_jmp != DISAS_NEXT) {
107 break;
108 }
109
110
111
112
113
114 if (plugin_enabled) {
115 plugin_gen_insn_end();
116 }
117
118
119
120 if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
121 db->is_jmp = DISAS_TOO_MANY;
122 break;
123 }
124 }
125
126
127 ops->tb_stop(db, cpu);
128 gen_tb_end(db->tb, db->num_insns - bp_insn);
129
130 if (plugin_enabled) {
131 plugin_gen_tb_end(cpu);
132 }
133
134
135 db->tb->size = db->pc_next - db->pc_first;
136 db->tb->icount = db->num_insns;
137
138#ifdef DEBUG_DISAS
139 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
140 && qemu_log_in_addr_range(db->pc_first)) {
141 qemu_log_lock();
142 qemu_log("----------------\n");
143 ops->disas_log(db, cpu);
144 qemu_log("\n");
145 qemu_log_unlock();
146 }
147#endif
148}
149