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

Diff of /qemu/cpu-exec.c

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

revision 1.60 by bellard, Sun Aug 21 09:43:38 2005 UTC revision 1.61 by bellard, Sun Nov 20 10:35:40 2005 UTC
# Line 73  void cpu_resume_from_signal(CPUState *en Line 73  void cpu_resume_from_signal(CPUState *en
73      longjmp(env->jmp_env, 1);      longjmp(env->jmp_env, 1);
74  }  }
75    
76    
77    static TranslationBlock *tb_find_slow(target_ulong pc,
78                                          target_ulong cs_base,
79                                          unsigned int flags)
80    {
81        TranslationBlock *tb, **ptb1;
82        int code_gen_size;
83        unsigned int h;
84        target_ulong phys_pc, phys_page1, phys_page2, virt_page2;
85        uint8_t *tc_ptr;
86        
87        spin_lock(&tb_lock);
88    
89        tb_invalidated_flag = 0;
90        
91        regs_to_env(); /* XXX: do it just before cpu_gen_code() */
92        
93        /* find translated block using physical mappings */
94        phys_pc = get_phys_addr_code(env, pc);
95        phys_page1 = phys_pc & TARGET_PAGE_MASK;
96        phys_page2 = -1;
97        h = tb_phys_hash_func(phys_pc);
98        ptb1 = &tb_phys_hash[h];
99        for(;;) {
100            tb = *ptb1;
101            if (!tb)
102                goto not_found;
103            if (tb->pc == pc &&
104                tb->page_addr[0] == phys_page1 &&
105                tb->cs_base == cs_base &&
106                tb->flags == flags) {
107                /* check next page if needed */
108                if (tb->page_addr[1] != -1) {
109                    virt_page2 = (pc & TARGET_PAGE_MASK) +
110                        TARGET_PAGE_SIZE;
111                    phys_page2 = get_phys_addr_code(env, virt_page2);
112                    if (tb->page_addr[1] == phys_page2)
113                        goto found;
114                } else {
115                    goto found;
116                }
117            }
118            ptb1 = &tb->phys_hash_next;
119        }
120     not_found:
121        /* if no translated code available, then translate it now */
122        tb = tb_alloc(pc);
123        if (!tb) {
124            /* flush must be done */
125            tb_flush(env);
126            /* cannot fail at this point */
127            tb = tb_alloc(pc);
128            /* don't forget to invalidate previous TB info */
129            T0 = 0;
130        }
131        tc_ptr = code_gen_ptr;
132        tb->tc_ptr = tc_ptr;
133        tb->cs_base = cs_base;
134        tb->flags = flags;
135        cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);
136        code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
137        
138        /* check next page if needed */
139        virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
140        phys_page2 = -1;
141        if ((pc & TARGET_PAGE_MASK) != virt_page2) {
142            phys_page2 = get_phys_addr_code(env, virt_page2);
143        }
144        tb_link_phys(tb, phys_pc, phys_page2);
145        
146     found:
147        if (tb_invalidated_flag) {
148            /* as some TB could have been invalidated because
149               of memory exceptions while generating the code, we
150               must recompute the hash index here */
151            T0 = 0;
152        }
153        /* we add the TB in the virtual pc hash table */
154        env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
155        spin_unlock(&tb_lock);
156        return tb;
157    }
158    
159    static inline TranslationBlock *tb_find_fast(void)
160    {
161        TranslationBlock *tb;
162        target_ulong cs_base, pc;
163        unsigned int flags;
164    
165        /* we record a subset of the CPU state. It will
166           always be the same before a given translated block
167           is executed. */
168    #if defined(TARGET_I386)
169        flags = env->hflags;
170        flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));
171        cs_base = env->segs[R_CS].base;
172        pc = cs_base + env->eip;
173    #elif defined(TARGET_ARM)
174        flags = env->thumb | (env->vfp.vec_len << 1)
175            | (env->vfp.vec_stride << 4);
176        cs_base = 0;
177        pc = env->regs[15];
178    #elif defined(TARGET_SPARC)
179    #ifdef TARGET_SPARC64
180        flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
181    #else
182        flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);
183    #endif
184        cs_base = env->npc;
185        pc = env->pc;
186    #elif defined(TARGET_PPC)
187        flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |
188            (msr_se << MSR_SE) | (msr_le << MSR_LE);
189        cs_base = 0;
190        pc = env->nip;
191    #elif defined(TARGET_MIPS)
192        flags = env->hflags & MIPS_HFLAGS_TMASK;
193        cs_base = NULL;
194        pc = env->PC;
195    #else
196    #error unsupported CPU
197    #endif
198        tb = env->tb_jmp_cache[tb_jmp_cache_hash_func(pc)];
199        if (__builtin_expect(!tb || tb->pc != pc || tb->cs_base != cs_base ||
200                             tb->flags != flags, 0)) {
201            tb = tb_find_slow(pc, cs_base, flags);
202        }
203        return tb;
204    }
205    
206    
207  /* main execution loop */  /* main execution loop */
208    
209  int cpu_exec(CPUState *env1)  int cpu_exec(CPUState *env1)
# Line 115  int cpu_exec(CPUState *env1) Line 246  int cpu_exec(CPUState *env1)
246  #ifdef __sparc__  #ifdef __sparc__
247      int saved_i7, tmp_T0;      int saved_i7, tmp_T0;
248  #endif  #endif
249      int code_gen_size, ret, interrupt_request;      int ret, interrupt_request;
250      void (*gen_func)(void);      void (*gen_func)(void);
251      TranslationBlock *tb, **ptb;      TranslationBlock *tb;
     target_ulong cs_base, pc;  
252      uint8_t *tc_ptr;      uint8_t *tc_ptr;
     unsigned int flags;  
253    
254      /* first we save global registers */      /* first we save global registers */
255      saved_env = env;      saved_env = env;
# Line 290  int cpu_exec(CPUState *env1) Line 419  int cpu_exec(CPUState *env1)
419                      }                      }
420  #endif  #endif
421                      if (msr_ee != 0) {                      if (msr_ee != 0) {
422                      if ((interrupt_request & CPU_INTERRUPT_HARD)) {                          if ((interrupt_request & CPU_INTERRUPT_HARD)) {
423                              /* Raise it */                              /* Raise it */
424                              env->exception_index = EXCP_EXTERNAL;                              env->exception_index = EXCP_EXTERNAL;
425                              env->error_code = 0;                              env->error_code = 0;
426                              do_interrupt(env);                              do_interrupt(env);
427                          env->interrupt_request &= ~CPU_INTERRUPT_HARD;                              env->interrupt_request &= ~CPU_INTERRUPT_HARD;
428                          } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {  #ifdef __sparc__
429                              /* Raise it */                              tmp_T0 = 0;
430                              env->exception_index = EXCP_DECR;  #else
431                              env->error_code = 0;                              T0 = 0;
432                              do_interrupt(env);  #endif
433                            } else if ((interrupt_request & CPU_INTERRUPT_TIMER)) {
434                                /* Raise it */
435                                env->exception_index = EXCP_DECR;
436                                env->error_code = 0;
437                                do_interrupt(env);
438                              env->interrupt_request &= ~CPU_INTERRUPT_TIMER;                              env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
439                          }  #ifdef __sparc__
440                                tmp_T0 = 0;
441    #else
442                                T0 = 0;
443    #endif
444                            }
445                      }                      }
446  #elif defined(TARGET_MIPS)  #elif defined(TARGET_MIPS)
447                      if ((interrupt_request & CPU_INTERRUPT_HARD) &&                      if ((interrupt_request & CPU_INTERRUPT_HARD) &&
# Line 316  int cpu_exec(CPUState *env1) Line 455  int cpu_exec(CPUState *env1)
455                          env->error_code = 0;                          env->error_code = 0;
456                          do_interrupt(env);                          do_interrupt(env);
457                          env->interrupt_request &= ~CPU_INTERRUPT_HARD;                          env->interrupt_request &= ~CPU_INTERRUPT_HARD;
458    #ifdef __sparc__
459                            tmp_T0 = 0;
460    #else
461                            T0 = 0;
462    #endif
463                      }                      }
464  #elif defined(TARGET_SPARC)  #elif defined(TARGET_SPARC)
465                      if ((interrupt_request & CPU_INTERRUPT_HARD) &&                      if ((interrupt_request & CPU_INTERRUPT_HARD) &&
# Line 329  int cpu_exec(CPUState *env1) Line 473  int cpu_exec(CPUState *env1)
473                              env->interrupt_request &= ~CPU_INTERRUPT_HARD;                              env->interrupt_request &= ~CPU_INTERRUPT_HARD;
474                              do_interrupt(env->interrupt_index);                              do_interrupt(env->interrupt_index);
475                              env->interrupt_index = 0;                              env->interrupt_index = 0;
476    #ifdef __sparc__
477                                tmp_T0 = 0;
478    #else
479                                T0 = 0;
480    #endif
481                          }                          }
482                      } else if (interrupt_request & CPU_INTERRUPT_TIMER) {                      } else if (interrupt_request & CPU_INTERRUPT_TIMER) {
483                          //do_interrupt(0, 0, 0, 0, 0);                          //do_interrupt(0, 0, 0, 0, 0);
# Line 399  int cpu_exec(CPUState *env1) Line 548  int cpu_exec(CPUState *env1)
548  #endif  #endif
549                  }                  }
550  #endif  #endif
551                  /* we record a subset of the CPU state. It will                  tb = tb_find_fast();
                    always be the same before a given translated block  
                    is executed. */  
 #if defined(TARGET_I386)  
                 flags = env->hflags;  
                 flags |= (env->eflags & (IOPL_MASK | TF_MASK | VM_MASK));  
                 cs_base = env->segs[R_CS].base;  
                 pc = cs_base + env->eip;  
 #elif defined(TARGET_ARM)  
                 flags = env->thumb | (env->vfp.vec_len << 1)  
                         | (env->vfp.vec_stride << 4);  
                 cs_base = 0;  
                 pc = env->regs[15];  
 #elif defined(TARGET_SPARC)  
 #ifdef TARGET_SPARC64  
                 flags = (env->pstate << 2) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);  
 #else  
                 flags = env->psrs | ((env->mmuregs[0] & (MMU_E | MMU_NF)) << 1);  
 #endif  
                 cs_base = env->npc;  
                 pc = env->pc;  
 #elif defined(TARGET_PPC)  
                 flags = (msr_pr << MSR_PR) | (msr_fp << MSR_FP) |  
                     (msr_se << MSR_SE) | (msr_le << MSR_LE);  
                 cs_base = 0;  
                 pc = env->nip;  
 #elif defined(TARGET_MIPS)  
                 flags = env->hflags & MIPS_HFLAGS_TMASK;  
                 cs_base = NULL;  
                 pc = env->PC;  
 #else  
 #error unsupported CPU  
 #endif  
                 tb = tb_find(&ptb, pc, cs_base,  
                              flags);  
                 if (!tb) {  
                     TranslationBlock **ptb1;  
                     unsigned int h;  
                     target_ulong phys_pc, phys_page1, phys_page2, virt_page2;  
                       
                       
                     spin_lock(&tb_lock);  
   
                     tb_invalidated_flag = 0;  
                       
                     regs_to_env(); /* XXX: do it just before cpu_gen_code() */  
   
                     /* find translated block using physical mappings */  
                     phys_pc = get_phys_addr_code(env, pc);  
                     phys_page1 = phys_pc & TARGET_PAGE_MASK;  
                     phys_page2 = -1;  
                     h = tb_phys_hash_func(phys_pc);  
                     ptb1 = &tb_phys_hash[h];  
                     for(;;) {  
                         tb = *ptb1;  
                         if (!tb)  
                             goto not_found;  
                         if (tb->pc == pc &&  
                             tb->page_addr[0] == phys_page1 &&  
                             tb->cs_base == cs_base &&  
                             tb->flags == flags) {  
                             /* check next page if needed */  
                             if (tb->page_addr[1] != -1) {  
                                 virt_page2 = (pc & TARGET_PAGE_MASK) +  
                                     TARGET_PAGE_SIZE;  
                                 phys_page2 = get_phys_addr_code(env, virt_page2);  
                                 if (tb->page_addr[1] == phys_page2)  
                                     goto found;  
                             } else {  
                                 goto found;  
                             }  
                         }  
                         ptb1 = &tb->phys_hash_next;  
                     }  
                 not_found:  
                     /* if no translated code available, then translate it now */  
                     tb = tb_alloc(pc);  
                     if (!tb) {  
                         /* flush must be done */  
                         tb_flush(env);  
                         /* cannot fail at this point */  
                         tb = tb_alloc(pc);  
                         /* don't forget to invalidate previous TB info */  
                         ptb = &tb_hash[tb_hash_func(pc)];  
                         T0 = 0;  
                     }  
                     tc_ptr = code_gen_ptr;  
                     tb->tc_ptr = tc_ptr;  
                     tb->cs_base = cs_base;  
                     tb->flags = flags;  
                     cpu_gen_code(env, tb, CODE_GEN_MAX_SIZE, &code_gen_size);  
                     code_gen_ptr = (void *)(((unsigned long)code_gen_ptr + code_gen_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));  
                       
                     /* check next page if needed */  
                     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;  
                     phys_page2 = -1;  
                     if ((pc & TARGET_PAGE_MASK) != virt_page2) {  
                         phys_page2 = get_phys_addr_code(env, virt_page2);  
                     }  
                     tb_link_phys(tb, phys_pc, phys_page2);  
   
                 found:  
                     if (tb_invalidated_flag) {  
                         /* as some TB could have been invalidated because  
                            of memory exceptions while generating the code, we  
                            must recompute the hash index here */  
                         ptb = &tb_hash[tb_hash_func(pc)];  
                         while (*ptb != NULL)  
                             ptb = &(*ptb)->hash_next;  
                         T0 = 0;  
                     }  
                     /* we add the TB in the virtual pc hash table */  
                     *ptb = tb;  
                     tb->hash_next = NULL;  
                     tb_link(tb);  
                     spin_unlock(&tb_lock);  
                 }  
552  #ifdef DEBUG_EXEC  #ifdef DEBUG_EXEC
553                  if ((loglevel & CPU_LOG_EXEC)) {                  if ((loglevel & CPU_LOG_EXEC)) {
554                      fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",                      fprintf(logfile, "Trace 0x%08lx [" TARGET_FMT_lx "] %s\n",
# Line 526  int cpu_exec(CPUState *env1) Line 559  int cpu_exec(CPUState *env1)
559  #ifdef __sparc__  #ifdef __sparc__
560                  T0 = tmp_T0;                  T0 = tmp_T0;
561  #endif        #endif      
562                  /* see if we can patch the calling TB. */                  /* see if we can patch the calling TB. When the TB
563                       spans two pages, we cannot safely do a direct
564                       jump. */
565                  {                  {
566                      if (T0 != 0                      if (T0 != 0 &&
567                            tb->page_addr[1] == -1
568  #if defined(TARGET_I386) && defined(USE_CODE_COPY)  #if defined(TARGET_I386) && defined(USE_CODE_COPY)
569                      && (tb->cflags & CF_CODE_COPY) ==                      && (tb->cflags & CF_CODE_COPY) ==
570                      (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)                      (((TranslationBlock *)(T0 & ~3))->cflags & CF_CODE_COPY)

Legend:
Removed from v.1.60  
changed lines
  Added in v.1.61

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