VirtualBox

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

Last change on this file since 13762 was 11982, checked in by vboxsync, 16 years ago

All: license header changes for 2.0 (OSE headers, add Sun GPL/LGPL disclaimer)

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

© 2023 Oracle
ContactPrivacy policyTerms of Use