VirtualBox

source: vbox/trunk/src/recompiler/translate-all.c@ 5999

Last change on this file since 5999 was 2422, checked in by vboxsync, 18 years ago

Removed the old recompiler code.

  • Property svn:eol-style set to native
File size: 8.9 KB
Line 
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, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25
26#include "config.h"
27
28#define NO_CPU_IO_DEFS
29#include "cpu.h"
30#include "exec-all.h"
31#include "disas.h"
32
33extern int dyngen_code(uint8_t *gen_code_buf,
34 uint16_t *label_offsets, uint16_t *jmp_offsets,
35 const uint16_t *opc_buf, const uint32_t *opparam_buf, const long *gen_labels);
36
37enum {
38#define DEF(s, n, copy_size) INDEX_op_ ## s,
39#include "opc.h"
40#undef DEF
41 NB_OPS,
42};
43
44uint16_t gen_opc_buf[OPC_BUF_SIZE];
45uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
46long gen_labels[OPC_BUF_SIZE];
47int nb_gen_labels;
48
49target_ulong gen_opc_pc[OPC_BUF_SIZE];
50uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
51#if defined(TARGET_I386)
52uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
53#elif defined(TARGET_SPARC)
54target_ulong gen_opc_npc[OPC_BUF_SIZE];
55target_ulong gen_opc_jump_pc[2];
56#elif defined(TARGET_MIPS)
57uint32_t gen_opc_hflags[OPC_BUF_SIZE];
58#endif
59
60int code_copy_enabled = 1;
61
62#ifdef DEBUG_DISAS
63static const char *op_str[] = {
64#define DEF(s, n, copy_size) #s,
65#include "opc.h"
66#undef DEF
67};
68
69static uint8_t op_nb_args[] = {
70#define DEF(s, n, copy_size) n,
71#include "opc.h"
72#undef DEF
73};
74#endif /* bird: opc_copy_size is used ouside DEBUG_DISAS and VBOX isn't necessarily defining DEBUG_DISAS presently. */
75
76static const unsigned short opc_copy_size[] = {
77#define DEF(s, n, copy_size) copy_size,
78#include "opc.h"
79#undef DEF
80};
81
82#ifdef DEBUG_DISAS /* bird: see previous bird comment. */
83void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
84{
85 const uint16_t *opc_ptr;
86 const uint32_t *opparam_ptr;
87 int c, n, i;
88
89 opc_ptr = opc_buf;
90 opparam_ptr = opparam_buf;
91 for(;;) {
92 c = *opc_ptr++;
93 n = op_nb_args[c];
94 fprintf(logfile, "0x%04x: %s",
95 (int)(opc_ptr - opc_buf - 1), op_str[c]);
96 for(i = 0; i < n; i++) {
97 fprintf(logfile, " 0x%x", opparam_ptr[i]);
98 }
99 fprintf(logfile, "\n");
100 if (c == INDEX_op_end)
101 break;
102 opparam_ptr += n;
103 }
104}
105
106#endif
107
108/* compute label info */
109static void dyngen_labels(long *gen_labels, int nb_gen_labels,
110 uint8_t *gen_code_buf, const uint16_t *opc_buf)
111{
112 uint8_t *gen_code_ptr;
113 int c, i;
114 unsigned long gen_code_addr[OPC_BUF_SIZE];
115
116 if (nb_gen_labels == 0)
117 return;
118 /* compute the address of each op code */
119
120 gen_code_ptr = gen_code_buf;
121 i = 0;
122 for(;;) {
123 c = opc_buf[i];
124 gen_code_addr[i] =(unsigned long)gen_code_ptr;
125 if (c == INDEX_op_end)
126 break;
127 gen_code_ptr += opc_copy_size[c];
128 i++;
129 }
130
131 /* compute the address of each label */
132 for(i = 0; i < nb_gen_labels; i++) {
133 gen_labels[i] = gen_code_addr[gen_labels[i]];
134 }
135}
136
137/* return non zero if the very first instruction is invalid so that
138 the virtual CPU can trigger an exception.
139
140 '*gen_code_size_ptr' contains the size of the generated code (host
141 code).
142*/
143int cpu_gen_code(CPUState *env, TranslationBlock *tb,
144 int max_code_size, int *gen_code_size_ptr)
145{
146 uint8_t *gen_code_buf;
147 int gen_code_size;
148
149#ifdef USE_CODE_COPY
150 if (code_copy_enabled &&
151 cpu_gen_code_copy(env, tb, max_code_size, &gen_code_size) == 0) {
152 /* nothing more to do */
153 } else
154#endif
155 {
156#ifdef VBOX
157 RAWEx_ProfileStart(env, STATS_QEMU_COMPILATION);
158 if (gen_intermediate_code(env, tb) < 0)
159 {
160 RAWEx_ProfileStop(env, STATS_QEMU_COMPILATION);
161 return -1;
162 }
163#else /* !VBOX */
164 if (gen_intermediate_code(env, tb) < 0)
165 return -1;
166#endif /* !VBOX */
167
168 /* generate machine code */
169 tb->tb_next_offset[0] = 0xffff;
170 tb->tb_next_offset[1] = 0xffff;
171 gen_code_buf = tb->tc_ptr;
172#ifdef USE_DIRECT_JUMP
173 /* the following two entries are optional (only used for string ops) */
174 tb->tb_jmp_offset[2] = 0xffff;
175 tb->tb_jmp_offset[3] = 0xffff;
176#endif
177 dyngen_labels(gen_labels, nb_gen_labels, gen_code_buf, gen_opc_buf);
178
179 gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
180#ifdef USE_DIRECT_JUMP
181 tb->tb_jmp_offset,
182#else
183 NULL,
184#endif
185 gen_opc_buf, gen_opparam_buf, gen_labels);
186#ifdef VBOX
187 RAWEx_ProfileStop(env, STATS_QEMU_COMPILATION);
188#endif
189 }
190 *gen_code_size_ptr = gen_code_size;
191#ifdef DEBUG_DISAS
192 if (loglevel & CPU_LOG_TB_OUT_ASM) {
193 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
194 disas(logfile, tb->tc_ptr, *gen_code_size_ptr);
195 fprintf(logfile, "\n");
196 fflush(logfile);
197 }
198#endif
199 return 0;
200}
201
202/* The cpu state corresponding to 'searched_pc' is restored.
203 */
204int cpu_restore_state(TranslationBlock *tb,
205 CPUState *env, unsigned long searched_pc,
206 void *puc)
207{
208 int j, c;
209 unsigned long tc_ptr;
210 uint16_t *opc_ptr;
211
212#ifdef USE_CODE_COPY
213 if (tb->cflags & CF_CODE_COPY) {
214 return cpu_restore_state_copy(tb, env, searched_pc, puc);
215 }
216#endif
217 if (gen_intermediate_code_pc(env, tb) < 0)
218 return -1;
219
220 /* find opc index corresponding to search_pc */
221 tc_ptr = (unsigned long)tb->tc_ptr;
222 if (searched_pc < tc_ptr)
223 return -1;
224 j = 0;
225 opc_ptr = gen_opc_buf;
226 for(;;) {
227 c = *opc_ptr;
228 if (c == INDEX_op_end)
229 return -1;
230 tc_ptr += opc_copy_size[c];
231 if (searched_pc < tc_ptr)
232 break;
233 opc_ptr++;
234 }
235 j = opc_ptr - gen_opc_buf;
236 /* now find start of instruction before */
237 while (gen_opc_instr_start[j] == 0)
238 j--;
239#if defined(TARGET_I386)
240 {
241 int cc_op;
242#ifdef DEBUG_DISAS
243 if (loglevel & CPU_LOG_TB_OP) {
244 int i;
245 fprintf(logfile, "RESTORE:\n");
246 for(i=0;i<=j; i++) {
247 if (gen_opc_instr_start[i]) {
248 fprintf(logfile, "0x%04x: " TARGET_FMT_lx "\n", i, gen_opc_pc[i]);
249 }
250 }
251 fprintf(logfile, "spc=0x%08lx j=0x%x eip=" TARGET_FMT_lx " cs_base=%x\n",
252 searched_pc, j, gen_opc_pc[j] - tb->cs_base,
253 (uint32_t)tb->cs_base);
254 }
255#endif
256 env->eip = gen_opc_pc[j] - tb->cs_base;
257 cc_op = gen_opc_cc_op[j];
258 if (cc_op != CC_OP_DYNAMIC)
259 env->cc_op = cc_op;
260 }
261#elif defined(TARGET_ARM)
262 env->regs[15] = gen_opc_pc[j];
263#elif defined(TARGET_SPARC)
264 {
265 target_ulong npc;
266 env->pc = gen_opc_pc[j];
267 npc = gen_opc_npc[j];
268 if (npc == 1) {
269 /* dynamic NPC: already stored */
270 } else if (npc == 2) {
271 target_ulong t2 = (target_ulong)puc;
272 /* jump PC: use T2 and the jump targets of the translation */
273 if (t2)
274 env->npc = gen_opc_jump_pc[0];
275 else
276 env->npc = gen_opc_jump_pc[1];
277 } else {
278 env->npc = npc;
279 }
280 }
281#elif defined(TARGET_PPC)
282 {
283 int type;
284 /* for PPC, we need to look at the micro operation to get the
285 access type */
286 env->nip = gen_opc_pc[j];
287 switch(c) {
288#if defined(CONFIG_USER_ONLY)
289#define CASE3(op)\
290 case INDEX_op_ ## op ## _raw
291#else
292#define CASE3(op)\
293 case INDEX_op_ ## op ## _user:\
294 case INDEX_op_ ## op ## _kernel
295#endif
296
297 CASE3(stfd):
298 CASE3(stfs):
299 CASE3(lfd):
300 CASE3(lfs):
301 type = ACCESS_FLOAT;
302 break;
303 CASE3(lwarx):
304 type = ACCESS_RES;
305 break;
306 CASE3(stwcx):
307 type = ACCESS_RES;
308 break;
309 CASE3(eciwx):
310 CASE3(ecowx):
311 type = ACCESS_EXT;
312 break;
313 default:
314 type = ACCESS_INT;
315 break;
316 }
317 env->access_type = type;
318 }
319#elif defined(TARGET_M68K)
320 env->pc = gen_opc_pc[j];
321#elif defined(TARGET_MIPS)
322 env->PC = gen_opc_pc[j];
323 env->hflags &= ~MIPS_HFLAG_BMASK;
324 env->hflags |= gen_opc_hflags[j];
325#endif
326 return 0;
327}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette