]> git.proxmox.com Git - qemu.git/blob - exec-i386.c
log fix
[qemu.git] / exec-i386.c
1 /*
2 * i386 emulator main execution loop
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 "exec-i386.h"
21 #include "disas.h"
22
23 //#define DEBUG_EXEC
24 #define DEBUG_FLUSH
25 //#define DEBUG_SIGNAL
26
27 /* main execution loop */
28
29 /* maximum total translate dcode allocated */
30 #define CODE_GEN_BUFFER_SIZE (2048 * 1024)
31 //#define CODE_GEN_BUFFER_SIZE (128 * 1024)
32 #define CODE_GEN_MAX_SIZE 65536
33 #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
34
35 /* threshold to flush the translated code buffer */
36 #define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
37
38 #define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / 64)
39 #define CODE_GEN_HASH_BITS 15
40 #define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
41
42 typedef struct TranslationBlock {
43 unsigned long pc; /* simulated PC corresponding to this block (EIP + CS base) */
44 unsigned long cs_base; /* CS base for this block */
45 unsigned int flags; /* flags defining in which context the code was generated */
46 uint8_t *tc_ptr; /* pointer to the translated code */
47 struct TranslationBlock *hash_next; /* next matching block */
48 } TranslationBlock;
49
50 TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
51 TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
52 int nb_tbs;
53
54 uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
55 uint8_t *code_gen_ptr;
56
57 /* thread support */
58
59 #ifdef __powerpc__
60 static inline int testandset (int *p)
61 {
62 int ret;
63 __asm__ __volatile__ (
64 "0: lwarx %0,0,%1 ;"
65 " xor. %0,%3,%0;"
66 " bne 1f;"
67 " stwcx. %2,0,%1;"
68 " bne- 0b;"
69 "1: "
70 : "=&r" (ret)
71 : "r" (p), "r" (1), "r" (0)
72 : "cr0", "memory");
73 return ret;
74 }
75 #endif
76
77 #ifdef __i386__
78 static inline int testandset (int *p)
79 {
80 char ret;
81 long int readval;
82
83 __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
84 : "=q" (ret), "=m" (*p), "=a" (readval)
85 : "r" (1), "m" (*p), "a" (0)
86 : "memory");
87 return ret;
88 }
89 #endif
90
91 #ifdef __s390__
92 static inline int testandset (int *p)
93 {
94 int ret;
95
96 __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
97 " jl 0b"
98 : "=&d" (ret)
99 : "r" (1), "a" (p), "0" (*p)
100 : "cc", "memory" );
101 return ret;
102 }
103 #endif
104
105 int global_cpu_lock = 0;
106
107 void cpu_lock(void)
108 {
109 while (testandset(&global_cpu_lock));
110 }
111
112 void cpu_unlock(void)
113 {
114 global_cpu_lock = 0;
115 }
116
117 /* exception support */
118 /* NOTE: not static to force relocation generation by GCC */
119 void raise_exception(int exception_index)
120 {
121 /* NOTE: the register at this point must be saved by hand because
122 longjmp restore them */
123 #ifdef reg_EAX
124 env->regs[R_EAX] = EAX;
125 #endif
126 #ifdef reg_ECX
127 env->regs[R_ECX] = ECX;
128 #endif
129 #ifdef reg_EDX
130 env->regs[R_EDX] = EDX;
131 #endif
132 #ifdef reg_EBX
133 env->regs[R_EBX] = EBX;
134 #endif
135 #ifdef reg_ESP
136 env->regs[R_ESP] = ESP;
137 #endif
138 #ifdef reg_EBP
139 env->regs[R_EBP] = EBP;
140 #endif
141 #ifdef reg_ESI
142 env->regs[R_ESI] = ESI;
143 #endif
144 #ifdef reg_EDI
145 env->regs[R_EDI] = EDI;
146 #endif
147 env->exception_index = exception_index;
148 longjmp(env->jmp_env, 1);
149 }
150
151 #if defined(DEBUG_EXEC)
152 static const char *cc_op_str[] = {
153 "DYNAMIC",
154 "EFLAGS",
155 "MUL",
156 "ADDB",
157 "ADDW",
158 "ADDL",
159 "ADCB",
160 "ADCW",
161 "ADCL",
162 "SUBB",
163 "SUBW",
164 "SUBL",
165 "SBBB",
166 "SBBW",
167 "SBBL",
168 "LOGICB",
169 "LOGICW",
170 "LOGICL",
171 "INCB",
172 "INCW",
173 "INCL",
174 "DECB",
175 "DECW",
176 "DECL",
177 "SHLB",
178 "SHLW",
179 "SHLL",
180 "SARB",
181 "SARW",
182 "SARL",
183 };
184
185 static void cpu_x86_dump_state(FILE *f)
186 {
187 int eflags;
188 eflags = cc_table[CC_OP].compute_all();
189 eflags |= (DF & DF_MASK);
190 fprintf(f,
191 "EAX=%08x EBX=%08X ECX=%08x EDX=%08x\n"
192 "ESI=%08x EDI=%08X EBP=%08x ESP=%08x\n"
193 "CCS=%08x CCD=%08x CCO=%-8s EFL=%c%c%c%c%c%c%c\n"
194 "EIP=%08x\n",
195 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
196 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
197 env->cc_src, env->cc_dst, cc_op_str[env->cc_op],
198 eflags & DF_MASK ? 'D' : '-',
199 eflags & CC_O ? 'O' : '-',
200 eflags & CC_S ? 'S' : '-',
201 eflags & CC_Z ? 'Z' : '-',
202 eflags & CC_A ? 'A' : '-',
203 eflags & CC_P ? 'P' : '-',
204 eflags & CC_C ? 'C' : '-',
205 env->eip);
206 #if 1
207 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
208 (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
209 #endif
210 }
211
212 #endif
213
214 void cpu_x86_tblocks_init(void)
215 {
216 if (!code_gen_ptr) {
217 code_gen_ptr = code_gen_buffer;
218 }
219 }
220
221 /* flush all the translation blocks */
222 static void tb_flush(void)
223 {
224 int i;
225 #ifdef DEBUG_FLUSH
226 printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",
227 code_gen_ptr - code_gen_buffer,
228 nb_tbs,
229 (code_gen_ptr - code_gen_buffer) / nb_tbs);
230 #endif
231 nb_tbs = 0;
232 for(i = 0;i < CODE_GEN_HASH_SIZE; i++)
233 tb_hash[i] = NULL;
234 code_gen_ptr = code_gen_buffer;
235 /* XXX: flush processor icache at this point */
236 }
237
238 /* find a translation block in the translation cache. If not found,
239 return NULL and the pointer to the last element of the list in pptb */
240 static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
241 unsigned long pc,
242 unsigned long cs_base,
243 unsigned int flags)
244 {
245 TranslationBlock **ptb, *tb;
246 unsigned int h;
247
248 h = pc & (CODE_GEN_HASH_SIZE - 1);
249 ptb = &tb_hash[h];
250 for(;;) {
251 tb = *ptb;
252 if (!tb)
253 break;
254 if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
255 return tb;
256 ptb = &tb->hash_next;
257 }
258 *pptb = ptb;
259 return NULL;
260 }
261
262 /* allocate a new translation block. flush the translation buffer if
263 too many translation blocks or too much generated code */
264 static inline TranslationBlock *tb_alloc(void)
265 {
266 TranslationBlock *tb;
267 if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
268 (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
269 tb_flush();
270 tb = &tbs[nb_tbs++];
271 return tb;
272 }
273
274 int cpu_x86_exec(CPUX86State *env1)
275 {
276 int saved_T0, saved_T1, saved_A0;
277 CPUX86State *saved_env;
278 #ifdef reg_EAX
279 int saved_EAX;
280 #endif
281 #ifdef reg_ECX
282 int saved_ECX;
283 #endif
284 #ifdef reg_EDX
285 int saved_EDX;
286 #endif
287 #ifdef reg_EBX
288 int saved_EBX;
289 #endif
290 #ifdef reg_ESP
291 int saved_ESP;
292 #endif
293 #ifdef reg_EBP
294 int saved_EBP;
295 #endif
296 #ifdef reg_ESI
297 int saved_ESI;
298 #endif
299 #ifdef reg_EDI
300 int saved_EDI;
301 #endif
302 int code_gen_size, ret;
303 void (*gen_func)(void);
304 TranslationBlock *tb, **ptb;
305 uint8_t *tc_ptr, *cs_base, *pc;
306 unsigned int flags;
307
308 /* first we save global registers */
309 saved_T0 = T0;
310 saved_T1 = T1;
311 saved_A0 = A0;
312 saved_env = env;
313 env = env1;
314 #ifdef reg_EAX
315 saved_EAX = EAX;
316 EAX = env->regs[R_EAX];
317 #endif
318 #ifdef reg_ECX
319 saved_ECX = ECX;
320 ECX = env->regs[R_ECX];
321 #endif
322 #ifdef reg_EDX
323 saved_EDX = EDX;
324 EDX = env->regs[R_EDX];
325 #endif
326 #ifdef reg_EBX
327 saved_EBX = EBX;
328 EBX = env->regs[R_EBX];
329 #endif
330 #ifdef reg_ESP
331 saved_ESP = ESP;
332 ESP = env->regs[R_ESP];
333 #endif
334 #ifdef reg_EBP
335 saved_EBP = EBP;
336 EBP = env->regs[R_EBP];
337 #endif
338 #ifdef reg_ESI
339 saved_ESI = ESI;
340 ESI = env->regs[R_ESI];
341 #endif
342 #ifdef reg_EDI
343 saved_EDI = EDI;
344 EDI = env->regs[R_EDI];
345 #endif
346
347 /* put eflags in CPU temporary format */
348 CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
349 DF = 1 - (2 * ((env->eflags >> 10) & 1));
350 CC_OP = CC_OP_EFLAGS;
351 env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
352 env->interrupt_request = 0;
353
354 /* prepare setjmp context for exception handling */
355 if (setjmp(env->jmp_env) == 0) {
356 for(;;) {
357 if (env->interrupt_request) {
358 raise_exception(EXCP_INTERRUPT);
359 }
360 #ifdef DEBUG_EXEC
361 if (loglevel) {
362 cpu_x86_dump_state(logfile);
363 }
364 #endif
365 /* we compute the CPU state. We assume it will not
366 change during the whole generated block. */
367 flags = env->seg_cache[R_CS].seg_32bit << GEN_FLAG_CODE32_SHIFT;
368 flags |= env->seg_cache[R_SS].seg_32bit << GEN_FLAG_SS32_SHIFT;
369 flags |= (((unsigned long)env->seg_cache[R_DS].base |
370 (unsigned long)env->seg_cache[R_ES].base |
371 (unsigned long)env->seg_cache[R_SS].base) != 0) <<
372 GEN_FLAG_ADDSEG_SHIFT;
373 flags |= (env->eflags & VM_MASK) >> (17 - GEN_FLAG_VM_SHIFT);
374 cs_base = env->seg_cache[R_CS].base;
375 pc = cs_base + env->eip;
376 tb = tb_find(&ptb, (unsigned long)pc, (unsigned long)cs_base,
377 flags);
378 if (!tb) {
379 /* if no translated code available, then translate it now */
380 /* XXX: very inefficient: we lock all the cpus when
381 generating code */
382 cpu_lock();
383 tc_ptr = code_gen_ptr;
384 ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
385 &code_gen_size, pc, cs_base, flags);
386 /* if invalid instruction, signal it */
387 if (ret != 0) {
388 cpu_unlock();
389 raise_exception(EXCP06_ILLOP);
390 }
391 tb = tb_alloc();
392 *ptb = tb;
393 tb->pc = (unsigned long)pc;
394 tb->cs_base = (unsigned long)cs_base;
395 tb->flags = flags;
396 tb->tc_ptr = tc_ptr;
397 tb->hash_next = NULL;
398 code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
399 cpu_unlock();
400 }
401 if (loglevel) {
402 fprintf(logfile, "Trace 0x%08lx [0x%08lx] %s\n",
403 (long)tb->tc_ptr, (long)tb->pc,
404 lookup_symbol((void *)tb->pc));
405 fflush(logfile);
406 }
407 /* execute the generated code */
408 tc_ptr = tb->tc_ptr;
409 gen_func = (void *)tc_ptr;
410 gen_func();
411 }
412 }
413 ret = env->exception_index;
414
415 /* restore flags in standard format */
416 env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
417
418 /* restore global registers */
419 #ifdef reg_EAX
420 EAX = saved_EAX;
421 #endif
422 #ifdef reg_ECX
423 ECX = saved_ECX;
424 #endif
425 #ifdef reg_EDX
426 EDX = saved_EDX;
427 #endif
428 #ifdef reg_EBX
429 EBX = saved_EBX;
430 #endif
431 #ifdef reg_ESP
432 ESP = saved_ESP;
433 #endif
434 #ifdef reg_EBP
435 EBP = saved_EBP;
436 #endif
437 #ifdef reg_ESI
438 ESI = saved_ESI;
439 #endif
440 #ifdef reg_EDI
441 EDI = saved_EDI;
442 #endif
443 T0 = saved_T0;
444 T1 = saved_T1;
445 A0 = saved_A0;
446 env = saved_env;
447 return ret;
448 }
449
450 void cpu_x86_interrupt(CPUX86State *s)
451 {
452 s->interrupt_request = 1;
453 }
454
455
456 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
457 {
458 CPUX86State *saved_env;
459
460 saved_env = env;
461 env = s;
462 load_seg(seg_reg, selector);
463 env = saved_env;
464 }
465
466 #undef EAX
467 #undef ECX
468 #undef EDX
469 #undef EBX
470 #undef ESP
471 #undef EBP
472 #undef ESI
473 #undef EDI
474 #undef EIP
475 #include <signal.h>
476 #include <sys/ucontext.h>
477
478 static inline int handle_cpu_signal(unsigned long pc,
479 sigset_t *old_set)
480 {
481 #ifdef DEBUG_SIGNAL
482 printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n",
483 pc, *(unsigned long *)old_set);
484 #endif
485 if (pc >= (unsigned long)code_gen_buffer &&
486 pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
487 /* the PC is inside the translated code. It means that we have
488 a virtual CPU fault */
489 /* we restore the process signal mask as the sigreturn should
490 do it */
491 sigprocmask(SIG_SETMASK, old_set, NULL);
492 /* XXX: need to compute virtual pc position by retranslating
493 code. The rest of the CPU state should be correct. */
494 raise_exception(EXCP0D_GPF);
495 /* never comes here */
496 return 1;
497 } else {
498 return 0;
499 }
500 }
501
502 int cpu_x86_signal_handler(int host_signum, struct siginfo *info,
503 void *puc)
504 {
505 #if defined(__i386__)
506 struct ucontext *uc = puc;
507 unsigned long pc;
508 sigset_t *pold_set;
509
510 #ifndef REG_EIP
511 /* for glibc 2.1 */
512 #define REG_EIP EIP
513 #endif
514 pc = uc->uc_mcontext.gregs[REG_EIP];
515 pold_set = &uc->uc_sigmask;
516 return handle_cpu_signal(pc, pold_set);
517 #else
518 #warning No CPU specific signal handler: cannot handle target SIGSEGV events
519 return 0;
520 #endif
521 }