1
2
3
4
5
6
7
8
9
10#include "qemu/osdep.h"
11#include "qemu/error-report.h"
12#include "tcg/tcg.h"
13#include "tcg/tcg-op.h"
14#include "exec/exec-all.h"
15#include "exec/gen-icount.h"
16#include "exec/log.h"
17#include "exec/translator.h"
18#include "exec/plugin-gen.h"
19#include "sysemu/replay.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
34bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
35{
36
37 if (tb_cflags(db->tb) & CF_NO_GOTO_TB) {
38 return false;
39 }
40
41
42 return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
43}
44
45void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
46 CPUState *cpu, TranslationBlock *tb, int max_insns)
47{
48 uint32_t cflags = tb_cflags(tb);
49 bool plugin_enabled;
50
51
52 db->tb = tb;
53 db->pc_first = tb->pc;
54 db->pc_next = db->pc_first;
55 db->is_jmp = DISAS_NEXT;
56 db->num_insns = 0;
57 db->max_insns = max_insns;
58 db->singlestep_enabled = cflags & CF_SINGLE_STEP;
59
60 ops->init_disas_context(db, cpu);
61 tcg_debug_assert(db->is_jmp == DISAS_NEXT);
62
63
64 tcg_clear_temp_count();
65
66
67 gen_tb_start(db->tb);
68 ops->tb_start(db, cpu);
69 tcg_debug_assert(db->is_jmp == DISAS_NEXT);
70
71 plugin_enabled = plugin_gen_tb_start(cpu, tb, cflags & CF_MEMI_ONLY);
72
73 while (true) {
74 db->num_insns++;
75 ops->insn_start(db, cpu);
76 tcg_debug_assert(db->is_jmp == DISAS_NEXT);
77
78 if (plugin_enabled) {
79 plugin_gen_insn_start(cpu, db);
80 }
81
82
83
84
85
86 if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
87
88 gen_io_start();
89 ops->translate_insn(db, cpu);
90 } else {
91
92 tcg_debug_assert(!(cflags & CF_MEMI_ONLY));
93 ops->translate_insn(db, cpu);
94 }
95
96
97 if (db->is_jmp != DISAS_NEXT) {
98 break;
99 }
100
101
102
103
104
105 if (plugin_enabled) {
106 plugin_gen_insn_end();
107 }
108
109
110
111 if (tcg_op_buf_full() || db->num_insns >= db->max_insns) {
112 db->is_jmp = DISAS_TOO_MANY;
113 break;
114 }
115 }
116
117
118 ops->tb_stop(db, cpu);
119 gen_tb_end(db->tb, db->num_insns);
120
121 if (plugin_enabled) {
122 plugin_gen_tb_end(cpu);
123 }
124
125
126 tb->size = db->pc_next - db->pc_first;
127 tb->icount = db->num_insns;
128
129#ifdef DEBUG_DISAS
130 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
131 && qemu_log_in_addr_range(db->pc_first)) {
132 FILE *logfile = qemu_log_lock();
133 qemu_log("----------------\n");
134 ops->disas_log(db, cpu);
135 qemu_log("\n");
136 qemu_log_unlock(logfile);
137 }
138#endif
139}
140