1 /* 2 * Host code generation 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18 */ 19 #include <stdarg.h> 20 #include <stdlib.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <inttypes.h> 24 25 #include "config.h" 26 27 #define NO_CPU_IO_DEFS 28 #include "cpu.h" 29 #include "exec-all.h" 30 #include "disas.h" 31 #include "tcg.h" 32 #include "qemu-timer.h" 33 34 /* code generation context */ 35 TCGContext tcg_ctx; 36 37 uint16_t gen_opc_buf[OPC_BUF_SIZE]; 38 TCGArg gen_opparam_buf[OPPARAM_BUF_SIZE]; 39 40 target_ulong gen_opc_pc[OPC_BUF_SIZE]; 41 uint16_t gen_opc_icount[OPC_BUF_SIZE]; 42 uint8_t gen_opc_instr_start[OPC_BUF_SIZE]; 43 #if defined(TARGET_I386) 44 uint8_t gen_opc_cc_op[OPC_BUF_SIZE]; 45 #elif defined(TARGET_SPARC) 46 target_ulong gen_opc_npc[OPC_BUF_SIZE]; 47 target_ulong gen_opc_jump_pc[2]; 48 #elif defined(TARGET_MIPS) || defined(TARGET_SH4) 49 uint32_t gen_opc_hflags[OPC_BUF_SIZE]; 50 #endif 51 52 #ifdef CONFIG_MEMCHECK 53 /* 54 * Memchecker code in this module copies TB PC <-> Guest PC map to the TB 55 * descriptor after guest code has been translated in cpu_gen_init routine. 56 */ 57 #include "memcheck/memcheck_api.h" 58 59 /* Array of (tb_pc, guest_pc) pairs, big enough for all translations. This 60 * array is used to obtain guest PC address from a translated PC address. 61 * tcg_gen_code_common will fill it up when memchecker is enabled. */ 62 static void* gen_opc_tpc2gpc[OPC_BUF_SIZE * 2]; 63 void** gen_opc_tpc2gpc_ptr = &gen_opc_tpc2gpc[0]; 64 /* Number of (tb_pc, guest_pc) pairs stored in gen_opc_tpc2gpc array. */ 65 unsigned int gen_opc_tpc2gpc_pairs; 66 #endif // CONFIG_MEMCHECK 67 68 /* XXX: suppress that */ 69 unsigned long code_gen_max_block_size(void) 70 { 71 static unsigned long max; 72 73 if (max == 0) { 74 max = TCG_MAX_OP_SIZE; 75 #define DEF(name, iarg, oarg, carg, flags) DEF2((iarg) + (oarg) + (carg)) 76 #define DEF2(copy_size) max = (copy_size > max) ? copy_size : max; 77 #include "tcg-opc.h" 78 #undef DEF 79 #undef DEF2 80 max *= OPC_MAX_SIZE; 81 } 82 83 return max; 84 } 85 86 void cpu_gen_init(void) 87 { 88 tcg_context_init(&tcg_ctx); 89 tcg_set_frame(&tcg_ctx, TCG_AREG0, offsetof(CPUState, temp_buf), 90 CPU_TEMP_BUF_NLONGS * sizeof(long)); 91 } 92 93 /* return non zero if the very first instruction is invalid so that 94 the virtual CPU can trigger an exception. 95 96 '*gen_code_size_ptr' contains the size of the generated code (host 97 code). 98 */ 99 int cpu_gen_code(CPUState *env, TranslationBlock *tb, int *gen_code_size_ptr) 100 { 101 TCGContext *s = &tcg_ctx; 102 uint8_t *gen_code_buf; 103 int gen_code_size; 104 #ifdef CONFIG_PROFILER 105 int64_t ti; 106 #endif 107 108 #ifdef CONFIG_PROFILER 109 s->tb_count1++; /* includes aborted translations because of 110 exceptions */ 111 ti = profile_getclock(); 112 #endif 113 tcg_func_start(s); 114 115 gen_intermediate_code(env, tb); 116 117 /* generate machine code */ 118 gen_code_buf = tb->tc_ptr; 119 tb->tb_next_offset[0] = 0xffff; 120 tb->tb_next_offset[1] = 0xffff; 121 s->tb_next_offset = tb->tb_next_offset; 122 #ifdef USE_DIRECT_JUMP 123 s->tb_jmp_offset = tb->tb_jmp_offset; 124 s->tb_next = NULL; 125 /* the following two entries are optional (only used for string ops) */ 126 /* XXX: not used ? */ 127 tb->tb_jmp_offset[2] = 0xffff; 128 tb->tb_jmp_offset[3] = 0xffff; 129 #else 130 s->tb_jmp_offset = NULL; 131 s->tb_next = tb->tb_next; 132 #endif 133 134 #ifdef CONFIG_PROFILER 135 s->tb_count++; 136 s->interm_time += profile_getclock() - ti; 137 s->code_time -= profile_getclock(); 138 #endif 139 gen_code_size = tcg_gen_code(s, gen_code_buf); 140 *gen_code_size_ptr = gen_code_size; 141 #ifdef CONFIG_PROFILER 142 s->code_time += profile_getclock(); 143 s->code_in_len += tb->size; 144 s->code_out_len += gen_code_size; 145 #endif 146 147 #ifdef CONFIG_MEMCHECK 148 /* Save translated PC -> guest PC map into TB. */ 149 if (memcheck_enabled && gen_opc_tpc2gpc_pairs && is_cpu_user(env)) { 150 tb->tpc2gpc = 151 qemu_malloc(gen_opc_tpc2gpc_pairs * 2 * sizeof(uintptr_t)); 152 if (tb->tpc2gpc != NULL) { 153 memcpy(tb->tpc2gpc, gen_opc_tpc2gpc_ptr, 154 gen_opc_tpc2gpc_pairs * 2 * sizeof(uintptr_t)); 155 tb->tpc2gpc_pairs = gen_opc_tpc2gpc_pairs; 156 } 157 158 } 159 #endif // CONFIG_MEMCHECK 160 161 #ifdef DEBUG_DISAS 162 if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) { 163 qemu_log("OUT: [size=%d]\n", *gen_code_size_ptr); 164 log_disas(tb->tc_ptr, *gen_code_size_ptr); 165 qemu_log("\n"); 166 qemu_log_flush(); 167 } 168 #endif 169 return 0; 170 } 171 172 /* The cpu state corresponding to 'searched_pc' is restored. 173 */ 174 int cpu_restore_state(TranslationBlock *tb, 175 CPUState *env, unsigned long searched_pc) 176 { 177 TCGContext *s = &tcg_ctx; 178 int j; 179 unsigned long tc_ptr; 180 #ifdef CONFIG_PROFILER 181 int64_t ti; 182 #endif 183 184 #ifdef CONFIG_PROFILER 185 ti = profile_getclock(); 186 #endif 187 tcg_func_start(s); 188 189 gen_intermediate_code_pc(env, tb); 190 191 if (use_icount) { 192 /* Reset the cycle counter to the start of the block. */ 193 env->icount_decr.u16.low += tb->icount; 194 /* Clear the IO flag. */ 195 env->can_do_io = 0; 196 } 197 198 /* find opc index corresponding to search_pc */ 199 tc_ptr = (unsigned long)tb->tc_ptr; 200 if (searched_pc < tc_ptr) 201 return -1; 202 203 s->tb_next_offset = tb->tb_next_offset; 204 #ifdef USE_DIRECT_JUMP 205 s->tb_jmp_offset = tb->tb_jmp_offset; 206 s->tb_next = NULL; 207 #else 208 s->tb_jmp_offset = NULL; 209 s->tb_next = tb->tb_next; 210 #endif 211 j = tcg_gen_code_search_pc(s, (uint8_t *)tc_ptr, searched_pc - tc_ptr); 212 if (j < 0) 213 return -1; 214 /* now find start of instruction before */ 215 while (gen_opc_instr_start[j] == 0) 216 j--; 217 env->icount_decr.u16.low -= gen_opc_icount[j]; 218 219 restore_state_to_opc(env, tb, j); 220 221 #ifdef CONFIG_PROFILER 222 s->restore_time += profile_getclock() - ti; 223 s->restore_count++; 224 #endif 225 return 0; 226 } 227