| 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 */ |