/[qemu]/qemu/exec-i386.c
ViewVC logotype

Diff of /qemu/exec-i386.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.18 by bellard, Tue May 13 18:59:59 2003 UTC revision 1.19 by bellard, Wed May 14 19:00:11 2003 UTC
# Line 21  Line 21 
21  #include "disas.h"  #include "disas.h"
22    
23  //#define DEBUG_EXEC  //#define DEBUG_EXEC
 #define DEBUG_FLUSH  
24  //#define DEBUG_SIGNAL  //#define DEBUG_SIGNAL
25    
26  /* main execution loop */  /* main execution loop */
27    
 /* maximum total translate dcode allocated */  
 #define CODE_GEN_BUFFER_SIZE     (2048 * 1024)  
 //#define CODE_GEN_BUFFER_SIZE     (128 * 1024)  
 #define CODE_GEN_MAX_SIZE        65536  
 #define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */  
   
 /* threshold to flush the translated code buffer */  
 #define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)  
   
 #define CODE_GEN_MAX_BLOCKS    (CODE_GEN_BUFFER_SIZE / 64)  
 #define CODE_GEN_HASH_BITS     15  
 #define CODE_GEN_HASH_SIZE     (1 << CODE_GEN_HASH_BITS)  
   
 typedef struct TranslationBlock {  
     unsigned long pc;   /* simulated PC corresponding to this block (EIP + CS base) */  
     unsigned long cs_base; /* CS base for this block */  
     unsigned int flags; /* flags defining in which context the code was generated */  
     uint8_t *tc_ptr;    /* pointer to the translated code */  
     struct TranslationBlock *hash_next; /* next matching block */  
 } TranslationBlock;  
   
 TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];  
 TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];  
 int nb_tbs;  
   
 uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];  
 uint8_t *code_gen_ptr;  
   
28  /* thread support */  /* thread support */
29    
30  #ifdef __powerpc__  #ifdef __powerpc__
# Line 195  void raise_exception(int exception_index Line 166  void raise_exception(int exception_index
166      raise_exception_err(exception_index, 0);      raise_exception_err(exception_index, 0);
167  }  }
168    
 void cpu_x86_tblocks_init(void)  
 {  
     if (!code_gen_ptr) {  
         code_gen_ptr = code_gen_buffer;  
     }  
 }  
   
 /* flush all the translation blocks */  
 static void tb_flush(void)  
 {  
     int i;  
 #ifdef DEBUG_FLUSH  
     printf("gemu: flush code_size=%d nb_tbs=%d avg_tb_size=%d\n",  
            code_gen_ptr - code_gen_buffer,  
            nb_tbs,  
            (code_gen_ptr - code_gen_buffer) / nb_tbs);  
 #endif  
     nb_tbs = 0;  
     for(i = 0;i < CODE_GEN_HASH_SIZE; i++)  
         tb_hash[i] = NULL;  
     code_gen_ptr = code_gen_buffer;  
     /* XXX: flush processor icache at this point */  
 }  
   
 /* find a translation block in the translation cache. If not found,  
    return NULL and the pointer to the last element of the list in pptb */  
 static inline TranslationBlock *tb_find(TranslationBlock ***pptb,  
                                         unsigned long pc,  
                                         unsigned long cs_base,  
                                         unsigned int flags)  
 {  
     TranslationBlock **ptb, *tb;  
     unsigned int h;  
   
     h = pc & (CODE_GEN_HASH_SIZE - 1);  
     ptb = &tb_hash[h];  
 #if 0  
     /* XXX: hack to handle 16 bit modyfing code */  
     if (flags & (1 << GEN_FLAG_CODE32_SHIFT))  
 #endif  
         for(;;) {  
             tb = *ptb;  
             if (!tb)  
                 break;  
             if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)  
             return tb;  
             ptb = &tb->hash_next;  
         }  
     *pptb = ptb;  
     return NULL;  
 }  
   
 /* allocate a new translation block. flush the translation buffer if  
    too many translation blocks or too much generated code */  
 static inline TranslationBlock *tb_alloc(void)  
 {  
     TranslationBlock *tb;  
     if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||  
         (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)  
         tb_flush();  
     tb = &tbs[nb_tbs++];  
     return tb;  
 }  
   
169  int cpu_x86_exec(CPUX86State *env1)  int cpu_x86_exec(CPUX86State *env1)
170  {  {
171      int saved_T0, saved_T1, saved_A0;      int saved_T0, saved_T1, saved_A0;
# Line 287  int cpu_x86_exec(CPUX86State *env1) Line 194  int cpu_x86_exec(CPUX86State *env1)
194  #ifdef reg_EDI  #ifdef reg_EDI
195      int saved_EDI;      int saved_EDI;
196  #endif  #endif
197      int code_gen_size, ret;      int code_gen_size, ret, code_size;
198      void (*gen_func)(void);      void (*gen_func)(void);
199      TranslationBlock *tb, **ptb;      TranslationBlock *tb, **ptb;
200      uint8_t *tc_ptr, *cs_base, *pc;      uint8_t *tc_ptr, *cs_base, *pc;
# Line 390  int cpu_x86_exec(CPUX86State *env1) Line 297  int cpu_x86_exec(CPUX86State *env1)
297                  cpu_lock();                  cpu_lock();
298                  tc_ptr = code_gen_ptr;                  tc_ptr = code_gen_ptr;
299                  ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,                  ret = cpu_x86_gen_code(code_gen_ptr, CODE_GEN_MAX_SIZE,
300                                         &code_gen_size, pc, cs_base, flags);                                         &code_gen_size, pc, cs_base, flags,
301                                           &code_size);
302                  /* if invalid instruction, signal it */                  /* if invalid instruction, signal it */
303                  if (ret != 0) {                  if (ret != 0) {
304                      cpu_unlock();                      cpu_unlock();
305                      raise_exception(EXCP06_ILLOP);                      raise_exception(EXCP06_ILLOP);
306                  }                  }
307                  tb = tb_alloc();                  tb = tb_alloc((unsigned long)pc, code_size);
308                  *ptb = tb;                  *ptb = tb;
                 tb->pc = (unsigned long)pc;  
309                  tb->cs_base = (unsigned long)cs_base;                  tb->cs_base = (unsigned long)cs_base;
310                  tb->flags = flags;                  tb->flags = flags;
311                  tb->tc_ptr = tc_ptr;                  tb->tc_ptr = tc_ptr;
# Line 493  void cpu_x86_load_seg(CPUX86State *s, in Line 400  void cpu_x86_load_seg(CPUX86State *s, in
400  #include <sys/ucontext.h>  #include <sys/ucontext.h>
401    
402  /* 'pc' is the host PC at which the exception was raised. 'address' is  /* 'pc' is the host PC at which the exception was raised. 'address' is
403     the effective address of the memory exception */     the effective address of the memory exception. 'is_write' is 1 if a
404       write caused the exception and otherwise 0'. 'old_set' is the
405       signal set which should be restored */
406  static inline int handle_cpu_signal(unsigned long pc,  static inline int handle_cpu_signal(unsigned long pc,
407                                      unsigned long address,                                      unsigned long address,
408                                        int is_write,
409                                      sigset_t *old_set)                                      sigset_t *old_set)
410  {  {
411  #ifdef DEBUG_SIGNAL  #if defined(DEBUG_SIGNAL)
412      printf("gemu: SIGSEGV pc=0x%08lx oldset=0x%08lx\n",      printf("qemu: SIGSEGV pc=0x%08lx address=%08lx wr=%d oldset=0x%08lx\n",
413             pc, *(unsigned long *)old_set);             pc, address, is_write, *(unsigned long *)old_set);
414  #endif  #endif
415        if (is_write && page_unprotect(address)) {
416            sigprocmask(SIG_SETMASK, old_set, NULL);
417            return 1;
418        }
419      if (pc >= (unsigned long)code_gen_buffer &&      if (pc >= (unsigned long)code_gen_buffer &&
420          pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {          pc < (unsigned long)code_gen_buffer + CODE_GEN_BUFFER_SIZE) {
421          /* the PC is inside the translated code. It means that we have          /* the PC is inside the translated code. It means that we have
# Line 512  static inline int handle_cpu_signal(unsi Line 426  static inline int handle_cpu_signal(unsi
426          /* XXX: need to compute virtual pc position by retranslating          /* XXX: need to compute virtual pc position by retranslating
427             code. The rest of the CPU state should be correct. */             code. The rest of the CPU state should be correct. */
428          env->cr2 = address;          env->cr2 = address;
429          /* XXX: more precise exception code */          raise_exception_err(EXCP0E_PAGE, 4 | (is_write << 1));
         raise_exception_err(EXCP0E_PAGE, 4);  
430          /* never comes here */          /* never comes here */
431          return 1;          return 1;
432      } else {      } else {
# Line 531  int cpu_x86_signal_handler(int host_sign Line 444  int cpu_x86_signal_handler(int host_sign
444            
445  #ifndef REG_EIP  #ifndef REG_EIP
446  /* for glibc 2.1 */  /* for glibc 2.1 */
447  #define REG_EIP EIP  #define REG_EIP    EIP
448    #define REG_ERR    ERR
449    #define REG_TRAPNO TRAPNO
450  #endif  #endif
451      pc = uc->uc_mcontext.gregs[REG_EIP];      pc = uc->uc_mcontext.gregs[REG_EIP];
452      pold_set = &uc->uc_sigmask;      pold_set = &uc->uc_sigmask;
453      return handle_cpu_signal(pc, (unsigned long)info->si_addr, pold_set);      return handle_cpu_signal(pc, (unsigned long)info->si_addr,
454                                 uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe ?
455                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
456                                 pold_set);
457  #else  #else
458  #warning No CPU specific signal handler: cannot handle target SIGSEGV events  #warning No CPU specific signal handler: cannot handle target SIGSEGV events
459      return 0;      return 0;

Legend:
Removed from v.1.18  
changed lines
  Added in v.1.19

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26