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