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

Diff of /qemu/exec.c

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

revision 1.4 by bellard, Fri May 16 16:07:10 2003 UTC revision 1.5 by bellard, Sun May 25 16:46:15 2003 UTC
# Line 27  Line 27 
27  #include <sys/mman.h>  #include <sys/mman.h>
28    
29  #include "cpu-i386.h"  #include "cpu-i386.h"
30    #include "exec.h"
31    
32  //#define DEBUG_TB_INVALIDATE  //#define DEBUG_TB_INVALIDATE
33  #define DEBUG_FLUSH  #define DEBUG_FLUSH
# Line 212  static void page_flush_tb(void) Line 213  static void page_flush_tb(void)
213  }  }
214    
215  /* flush all the translation blocks */  /* flush all the translation blocks */
216    /* XXX: tb_flush is currently not thread safe */
217  void tb_flush(void)  void tb_flush(void)
218  {  {
219      int i;      int i;
# Line 226  void tb_flush(void) Line 228  void tb_flush(void)
228          tb_hash[i] = NULL;          tb_hash[i] = NULL;
229      page_flush_tb();      page_flush_tb();
230      code_gen_ptr = code_gen_buffer;      code_gen_ptr = code_gen_buffer;
231      /* XXX: flush processor icache at this point */      /* XXX: flush processor icache at this point if cache flush is
232           expensive */
233  }  }
234    
235  #ifdef DEBUG_TB_CHECK  #ifdef DEBUG_TB_CHECK
# Line 265  static void tb_page_check(void) Line 268  static void tb_page_check(void)
268      }      }
269  }  }
270    
271    void tb_jmp_check(TranslationBlock *tb)
272    {
273        TranslationBlock *tb1;
274        unsigned int n1;
275    
276        /* suppress any remaining jumps to this TB */
277        tb1 = tb->jmp_first;
278        for(;;) {
279            n1 = (long)tb1 & 3;
280            tb1 = (TranslationBlock *)((long)tb1 & ~3);
281            if (n1 == 2)
282                break;
283            tb1 = tb1->jmp_next[n1];
284        }
285        /* check end of list */
286        if (tb1 != tb) {
287            printf("ERROR: jmp_list from 0x%08lx\n", (long)tb);
288        }
289    }
290    
291  #endif  #endif
292    
293  /* invalidate one TB */  /* invalidate one TB */
# Line 282  static inline void tb_remove(Translation Line 305  static inline void tb_remove(Translation
305      }      }
306  }  }
307    
308    static inline void tb_jmp_remove(TranslationBlock *tb, int n)
309    {
310        TranslationBlock *tb1, **ptb;
311        unsigned int n1;
312    
313        ptb = &tb->jmp_next[n];
314        tb1 = *ptb;
315        if (tb1) {
316            /* find tb(n) in circular list */
317            for(;;) {
318                tb1 = *ptb;
319                n1 = (long)tb1 & 3;
320                tb1 = (TranslationBlock *)((long)tb1 & ~3);
321                if (n1 == n && tb1 == tb)
322                    break;
323                if (n1 == 2) {
324                    ptb = &tb1->jmp_first;
325                } else {
326                    ptb = &tb1->jmp_next[n1];
327                }
328            }
329            /* now we can suppress tb(n) from the list */
330            *ptb = tb->jmp_next[n];
331    
332            tb->jmp_next[n] = NULL;
333        }
334    }
335    
336    /* reset the jump entry 'n' of a TB so that it is not chained to
337       another TB */
338    static inline void tb_reset_jump(TranslationBlock *tb, int n)
339    {
340        tb_set_jmp_target(tb, n, (unsigned long)(tb->tc_ptr + tb->tb_next_offset[n]));
341    }
342    
343  static inline void tb_invalidate(TranslationBlock *tb, int parity)  static inline void tb_invalidate(TranslationBlock *tb, int parity)
344  {  {
345      PageDesc *p;      PageDesc *p;
346      unsigned int page_index1, page_index2;      unsigned int page_index1, page_index2;
347      unsigned int h;      unsigned int h, n1;
348        TranslationBlock *tb1, *tb2;
349        
350      /* remove the TB from the hash list */      /* remove the TB from the hash list */
351      h = tb_hash_func(tb->pc);      h = tb_hash_func(tb->pc);
352      tb_remove(&tb_hash[h], tb,      tb_remove(&tb_hash[h], tb,
# Line 305  static inline void tb_invalidate(Transla Line 364  static inline void tb_invalidate(Transla
364          tb_remove(&p->first_tb, tb,          tb_remove(&p->first_tb, tb,
365                    offsetof(TranslationBlock, page_next[page_index2 & 1]));                    offsetof(TranslationBlock, page_next[page_index2 & 1]));
366      }      }
367    
368        /* suppress this TB from the two jump lists */
369        tb_jmp_remove(tb, 0);
370        tb_jmp_remove(tb, 1);
371    
372        /* suppress any remaining jumps to this TB */
373        tb1 = tb->jmp_first;
374        for(;;) {
375            n1 = (long)tb1 & 3;
376            if (n1 == 2)
377                break;
378            tb1 = (TranslationBlock *)((long)tb1 & ~3);
379            tb2 = tb1->jmp_next[n1];
380            tb_reset_jump(tb1, n1);
381            tb1->jmp_next[n1] = NULL;
382            tb1 = tb2;
383        }
384        tb->jmp_first = (TranslationBlock *)((long)tb | 2); /* fail safe */
385  }  }
386    
387  /* invalidate all TBs which intersect with the target page starting at addr */  /* invalidate all TBs which intersect with the target page starting at addr */
# Line 367  static inline void tb_alloc_page(Transla Line 444  static inline void tb_alloc_page(Transla
444    
445  /* Allocate a new translation block. Flush the translation buffer if  /* Allocate a new translation block. Flush the translation buffer if
446     too many translation blocks or too much generated code. */     too many translation blocks or too much generated code. */
447  TranslationBlock *tb_alloc(unsigned long pc,  TranslationBlock *tb_alloc(unsigned long pc)
                            unsigned long size)  
448  {  {
449      TranslationBlock *tb;      TranslationBlock *tb;
     unsigned int page_index1, page_index2;  
450    
451      if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||      if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
452          (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)          (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
453          tb_flush();          return NULL;
454      tb = &tbs[nb_tbs++];      tb = &tbs[nb_tbs++];
455      tb->pc = pc;      tb->pc = pc;
456      tb->size = size;      return tb;
457    }
458    
459    /* link the tb with the other TBs */
460    void tb_link(TranslationBlock *tb)
461    {
462        unsigned int page_index1, page_index2;
463    
464      /* add in the page list */      /* add in the page list */
465      page_index1 = pc >> TARGET_PAGE_BITS;      page_index1 = tb->pc >> TARGET_PAGE_BITS;
466      tb_alloc_page(tb, page_index1);      tb_alloc_page(tb, page_index1);
467      page_index2 = (pc + size - 1) >> TARGET_PAGE_BITS;      page_index2 = (tb->pc + tb->size - 1) >> TARGET_PAGE_BITS;
468      if (page_index2 != page_index1) {      if (page_index2 != page_index1) {
469          tb_alloc_page(tb, page_index2);          tb_alloc_page(tb, page_index2);
470      }      }
471      return tb;      tb->jmp_first = (TranslationBlock *)((long)tb | 2);
472        tb->jmp_next[0] = NULL;
473        tb->jmp_next[1] = NULL;
474    
475        /* init original jump addresses */
476        if (tb->tb_next_offset[0] != 0xffff)
477            tb_reset_jump(tb, 0);
478        if (tb->tb_next_offset[1] != 0xffff)
479            tb_reset_jump(tb, 1);
480  }  }
481    
482  /* called from signal handler: invalidate the code and unprotect the  /* called from signal handler: invalidate the code and unprotect the

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

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