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