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