master
h 282 lines 8.79 KB
Raw
1 /*
2 * Generic intermediate code generation.
3 *
4 * Copyright (C) 2016-2017 Lluís Vilanova <vilanova@ac.upc.edu>
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
9
10 #ifndef EXEC__TRANSLATOR_H
11 #define EXEC__TRANSLATOR_H
12
13 /*
14 * Include this header from a target-specific file, and add a
15 *
16 * DisasContextBase base;
17 *
18 * member in your target-specific DisasContext.
19 */
20
21 #include "exec/memop.h"
22 #include "exec/vaddr.h"
23 #include "tcg/tcg.h"
24
25 /**
26 * DisasJumpType:
27 * @DISAS_NEXT: Next instruction in program order.
28 * @DISAS_TOO_MANY: Too many instructions translated.
29 * @DISAS_NORETURN: Following code is dead.
30 * @DISAS_TARGET_*: Start of target-specific conditions.
31 *
32 * What instruction to disassemble next.
33 */
34 typedef enum DisasJumpType {
35 DISAS_NEXT,
36 DISAS_TOO_MANY,
37 DISAS_NORETURN,
38 DISAS_TARGET_0,
39 DISAS_TARGET_1,
40 DISAS_TARGET_2,
41 DISAS_TARGET_3,
42 DISAS_TARGET_4,
43 DISAS_TARGET_5,
44 DISAS_TARGET_6,
45 DISAS_TARGET_7,
46 DISAS_TARGET_8,
47 DISAS_TARGET_9,
48 DISAS_TARGET_10,
49 DISAS_TARGET_11,
50 } DisasJumpType;
51
52 /**
53 * DisasContextBase:
54 * @tb: Translation block for this disassembly.
55 * @pc_first: Address of first guest instruction in this TB.
56 * @pc_next: Address of next guest instruction in this TB (current during
57 * disassembly).
58 * @is_jmp: What instruction to disassemble next.
59 * @num_insns: Number of translated instructions (including current).
60 * @max_insns: Maximum number of instructions to be translated in this TB.
61 * @plugin_enabled: TCG plugin enabled in this TB.
62 * @fake_insn: True if translator_fake_ldb used.
63 * @insn_start: The last op emitted by the insn_start hook,
64 * which is expected to be INDEX_op_insn_start.
65 *
66 * Architecture-agnostic disassembly context.
67 */
68 struct DisasContextBase {
69 TranslationBlock *tb;
70 vaddr pc_first;
71 vaddr pc_next;
72 DisasJumpType is_jmp;
73 int num_insns;
74 int max_insns;
75 bool plugin_enabled;
76 bool fake_insn;
77 uint8_t code_mmuidx;
78 struct TCGOp *insn_start;
79 void *host_addr[2];
80
81 /*
82 * Record insn data that we cannot read directly from host memory.
83 * There are only two reasons we cannot use host memory:
84 * (1) We are executing from I/O,
85 * (2) We are executing a synthetic instruction (s390x EX).
86 * In both cases we need record exactly one instruction,
87 * and thus the maximum amount of data we record is limited.
88 */
89 int record_start;
90 int record_len;
91 uint8_t record[32];
92 };
93
94 /**
95 * TranslatorOps:
96 * @init_disas_context:
97 * Initialize the target-specific portions of DisasContext struct.
98 * The generic DisasContextBase has already been initialized.
99 *
100 * @tb_start:
101 * Emit any code required before the start of the main loop,
102 * after the generic gen_tb_start().
103 *
104 * @insn_start:
105 * Emit the tcg_gen_insn_start opcode.
106 *
107 * @translate_insn:
108 * Disassemble one instruction and set db->pc_next for the start
109 * of the following instruction. Set db->is_jmp as necessary to
110 * terminate the main loop.
111 *
112 * @tb_stop:
113 * Emit any opcodes required to exit the TB, based on db->is_jmp.
114 *
115 * @disas_log:
116 * Print instruction disassembly to log.
117 */
118 typedef struct TranslatorOps {
119 void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
120 void (*tb_start)(DisasContextBase *db, CPUState *cpu);
121 void (*insn_start)(DisasContextBase *db, CPUState *cpu);
122 void (*translate_insn)(DisasContextBase *db, CPUState *cpu);
123 void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
124 bool (*disas_log)(const DisasContextBase *db, CPUState *cpu, FILE *f);
125 } TranslatorOps;
126
127 /**
128 * translator_loop:
129 * @cpu: Target vCPU.
130 * @tb: Translation block.
131 * @max_insns: Maximum number of insns to translate.
132 * @pc: guest virtual program counter address
133 * @host_pc: host physical program counter address
134 * @ops: Target-specific operations.
135 * @db: Disassembly context.
136 * @addr_type: TCG Type for addresses (TCG_TYPE_VA).
137 *
138 * Generic translator loop.
139 *
140 * Translation will stop in the following cases (in order):
141 * - When is_jmp set by #TranslatorOps::breakpoint_check.
142 * - set to DISAS_TOO_MANY exits after translating one more insn
143 * - set to any other value than DISAS_NEXT exits immediately.
144 * - When is_jmp set by #TranslatorOps::translate_insn.
145 * - set to any value other than DISAS_NEXT exits immediately.
146 * - When the TCG operation buffer is full.
147 * - When single-stepping is enabled (system-wide or on the current vCPU).
148 * - When too many instructions have been translated.
149 */
150 void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
151 vaddr pc, void *host_pc, const TranslatorOps *ops,
152 DisasContextBase *db, TCGType addr_type);
153
154 /**
155 * translator_use_goto_tb
156 * @db: Disassembly context
157 * @dest: target pc of the goto
158 *
159 * Return true if goto_tb is allowed between the current TB
160 * and the destination PC.
161 */
162 bool translator_use_goto_tb(DisasContextBase *db, vaddr dest);
163
164 /**
165 * translator_io_start
166 * @db: Disassembly context
167 *
168 * If icount is enabled, set cpu->can_do_io, adjust db->is_jmp to
169 * DISAS_TOO_MANY if it is still DISAS_NEXT, and return true.
170 * Otherwise return false.
171 */
172 bool translator_io_start(DisasContextBase *db);
173
174 /*
175 * Translator Load Functions
176 *
177 * These are intended to replace the direct usage of the cpu_ld*_code
178 * functions and are mandatory for front-ends that have been migrated
179 * to the common translator_loop. These functions are only intended
180 * to be called from the translation stage and should not be called
181 * from helper functions. Those functions should be converted to encode
182 * the relevant information at translation time.
183 */
184
185 uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc);
186 uint16_t translator_lduw_end(CPUArchState *env, DisasContextBase *db,
187 vaddr pc, MemOp endian);
188 uint32_t translator_ldl_end(CPUArchState *env, DisasContextBase *db,
189 vaddr pc, MemOp endian);
190 uint64_t translator_ldq_end(CPUArchState *env, DisasContextBase *db,
191 vaddr pc, MemOp endian);
192
193 #if !defined(TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API) \
194 && defined(COMPILING_PER_TARGET)
195 static inline uint16_t
196 translator_lduw(CPUArchState *env, DisasContextBase *db, vaddr pc)
197 {
198 return translator_lduw_end(env, db, pc, MO_TE);
199 }
200
201 static inline uint32_t
202 translator_ldl(CPUArchState *env, DisasContextBase *db, vaddr pc)
203 {
204 return translator_ldl_end(env, db, pc, MO_TE);
205 }
206
207 static inline uint64_t
208 translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc)
209 {
210 return translator_ldq_end(env, db, pc, MO_TE);
211 }
212
213 static inline uint16_t
214 translator_lduw_swap(CPUArchState *env, DisasContextBase *db,
215 vaddr pc, bool do_swap)
216 {
217 return translator_lduw_end(env, db, pc, MO_TE ^ (do_swap * MO_BSWAP));
218 }
219
220 static inline uint32_t
221 translator_ldl_swap(CPUArchState *env, DisasContextBase *db,
222 vaddr pc, bool do_swap)
223 {
224 return translator_ldl_end(env, db, pc, MO_TE ^ (do_swap * MO_BSWAP));
225 }
226
227 static inline uint64_t
228 translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
229 vaddr pc, bool do_swap)
230 {
231 return translator_ldq_end(env, db, pc, MO_TE ^ (do_swap * MO_BSWAP));
232 }
233 #endif /* !TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API && COMPILING_PER_TARGET */
234
235 /**
236 * translator_fake_ld - fake instruction load
237 * @db: Disassembly context
238 * @data: bytes of instruction
239 * @len: number of bytes
240 *
241 * This is a special case helper used where the instruction we are
242 * about to translate comes from somewhere else (e.g. being
243 * re-synthesised for s390x "ex"). It ensures we update other areas of
244 * the translator with details of the executed instruction.
245 */
246 void translator_fake_ld(DisasContextBase *db, const void *data, size_t len);
247
248 /**
249 * translator_st
250 * @db: disassembly context
251 * @dest: address to copy into
252 * @addr: virtual address within TB
253 * @len: length
254 *
255 * Copy @len bytes from @addr into @dest.
256 * All bytes must have been read during translation.
257 * Return true on success or false on failure.
258 */
259 bool translator_st(const DisasContextBase *db, void *dest,
260 vaddr addr, size_t len);
261
262 /**
263 * translator_st_len
264 * @db: disassembly context
265 *
266 * Return the number of bytes available to copy from the
267 * current translation block with translator_st.
268 */
269 size_t translator_st_len(const DisasContextBase *db);
270
271 /**
272 * translator_is_same_page
273 * @db: disassembly context
274 * @addr: virtual address within TB
275 *
276 * Return whether @addr is on the same page as where disassembly started.
277 * Translators can use this to enforce the rule that only single-insn
278 * translation blocks are allowed to cross page boundaries.
279 */
280 bool translator_is_same_page(const DisasContextBase *db, vaddr addr);
281
282 #endif /* EXEC__TRANSLATOR_H */