/[dynamips]/upstream/dynamips-0.2.7-RC2/mips64_jit.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /upstream/dynamips-0.2.7-RC2/mips64_jit.c

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

upstream/dynamips-0.2.6-RC5/mips64_jit.c revision 6 by dpavlin, Sat Oct 6 16:09:07 2007 UTC upstream/dynamips-0.2.7-RC1/mips64_jit.c revision 7 by dpavlin, Sat Oct 6 16:23:47 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   * Cisco 7200 (Predator) simulation platform.   * Cisco router simulation platform.
3   * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)   * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4   *   *
5   * MIPS64 JIT compiler.   * MIPS64 JIT compiler.
# Line 16  Line 16 
16  #include <fcntl.h>  #include <fcntl.h>
17  #include <assert.h>  #include <assert.h>
18    
 #include ARCH_INC_FILE  
   
 #include "rbtree.h"  
 #include "cp0.h"  
 #include "memory.h"  
19  #include "cpu.h"  #include "cpu.h"
20  #include "device.h"  #include "device.h"
21  #include "mips64.h"  #include "mips64.h"
22    #include "mips64_cp0.h"
23  #include "mips64_exec.h"  #include "mips64_exec.h"
24    #include "mips64_jit.h"
25  #include "insn_lookup.h"  #include "insn_lookup.h"
26    #include "memory.h"
27  #include "ptask.h"  #include "ptask.h"
28    
29    #include MIPS64_ARCH_INC_FILE
30    
31  #if DEBUG_BLOCK_TIMESTAMP  #if DEBUG_BLOCK_TIMESTAMP
32  static volatile m_uint64_t jit_jiffies = 0;  static volatile m_uint64_t jit_jiffies = 0;
33  #endif  #endif
34    
35  /* MIPS jump instructions for block scan */  /* MIPS jump instructions for block scan */
36  struct insn_jump mips64_insn_jumps[] = {  struct mips64_insn_jump mips64_insn_jumps[] = {
37     { "b"       , 0xffff0000, 0x10000000, 16, 1 },     { "b"       , 0xffff0000, 0x10000000, 16, 1 },
38     { "bal"     , 0xffff0000, 0x04110000, 16, 1 },     { "bal"     , 0xffff0000, 0x04110000, 16, 1 },
39     { "beq"     , 0xfc000000, 0x10000000, 16, 1 },     { "beq"     , 0xfc000000, 0x10000000, 16, 1 },
# Line 64  static void *mips64_jit_get_insn(int ind Line 64  static void *mips64_jit_get_insn(int ind
64     return(&mips64_insn_tags[index]);     return(&mips64_insn_tags[index]);
65  }  }
66    
67  static int mips64_jit_chk_lo(struct insn_tag *tag,int value)  static int mips64_jit_chk_lo(struct mips64_insn_tag *tag,int value)
68  {  {
69     return((value & tag->mask) == (tag->value & 0xFFFF));     return((value & tag->mask) == (tag->value & 0xFFFF));
70  }  }
71    
72  static int mips64_jit_chk_hi(struct insn_tag *tag,int value)  static int mips64_jit_chk_hi(struct mips64_insn_tag *tag,int value)
73  {  {
74     return((value & (tag->mask >> 16)) == (tag->value >> 16));     return((value & (tag->mask >> 16)) == (tag->value >> 16));
75  }  }
# Line 82  void mips64_jit_create_ilt(void) Line 82  void mips64_jit_create_ilt(void)
82     for(i=0,count=0;mips64_insn_tags[i].emit;i++)     for(i=0,count=0;mips64_insn_tags[i].emit;i++)
83        count++;        count++;
84    
85     ilt = ilt_create(count,     ilt = ilt_create(count+1,
86                      (ilt_get_insn_cbk_t)mips64_jit_get_insn,                      (ilt_get_insn_cbk_t)mips64_jit_get_insn,
87                      (ilt_check_cbk_t)mips64_jit_chk_lo,                      (ilt_check_cbk_t)mips64_jit_chk_lo,
88                      (ilt_check_cbk_t)mips64_jit_chk_hi);                      (ilt_check_cbk_t)mips64_jit_chk_hi);
# Line 141  int mips64_jit_init(cpu_mips_t *cpu) Line 141  int mips64_jit_init(cpu_mips_t *cpu)
141     }     }
142    
143     printf("CPU%u: carved JIT exec zone of %lu Mb into %lu pages of %u Kb.\n",     printf("CPU%u: carved JIT exec zone of %lu Mb into %lu pages of %u Kb.\n",
144            cpu->id,(u_long)(cpu->exec_page_area_size / 1048576),            cpu->gen->id,
145              (u_long)(cpu->exec_page_area_size / 1048576),
146            (u_long)cpu->exec_page_count,MIPS_JIT_BUFSIZE / 1024);            (u_long)cpu->exec_page_count,MIPS_JIT_BUFSIZE / 1024);
147     return(0);     return(0);
148  }  }
# Line 149  int mips64_jit_init(cpu_mips_t *cpu) Line 150  int mips64_jit_init(cpu_mips_t *cpu)
150  /* Flush the JIT */  /* Flush the JIT */
151  u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold)  u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold)
152  {  {
153     insn_block_t *p,*next;     mips64_jit_tcb_t *p,*next;
154     u_int count = 0;     u_int count = 0;
155    
156     if (!threshold)     if (!threshold)
157        threshold = (u_int)(-1);  /* UINT_MAX not defined everywhere */        threshold = (u_int)(-1);  /* UINT_MAX not defined everywhere */
158    
159     for(p=cpu->insn_block_list;p;p=next) {     for(p=cpu->tcb_list;p;p=next) {
160        next = p->next;        next = p->next;
161    
162        if (p->acc_count <= threshold) {        if (p->acc_count <= threshold) {
163           cpu->exec_phys_map[p->phys_page] = NULL;           cpu->exec_phys_map[p->phys_page] = NULL;
164           insn_block_free(cpu,p,TRUE);           mips64_jit_tcb_free(cpu,p,TRUE);
165           count++;           count++;
166        }        }
167     }     }
# Line 172  u_int mips64_jit_flush(cpu_mips_t *cpu,u Line 173  u_int mips64_jit_flush(cpu_mips_t *cpu,u
173  /* Shutdown the JIT */  /* Shutdown the JIT */
174  void mips64_jit_shutdown(cpu_mips_t *cpu)  void mips64_jit_shutdown(cpu_mips_t *cpu)
175  {    {  
176     insn_block_t *p,*next;     mips64_jit_tcb_t *p,*next;
177    
178     /* Flush the JIT */     /* Flush the JIT */
179     mips64_jit_flush(cpu,0);     mips64_jit_flush(cpu,0);
180    
181     /* Free the instruction blocks */     /* Free the instruction blocks */
182     for(p=cpu->insn_block_free_list;p;p=next) {     for(p=cpu->tcb_free_list;p;p=next) {
183        next = p->next;        next = p->next;
184        free(p);        free(p);
185     }     }
# Line 204  static inline insn_exec_page_t *exec_pag Line 205  static inline insn_exec_page_t *exec_pag
205     if (unlikely(!cpu->exec_page_free_list))     if (unlikely(!cpu->exec_page_free_list))
206     {     {
207        if (cpu->jit_flush_method) {        if (cpu->jit_flush_method) {
208           cpu_log(cpu,"JIT","flushing data structures (compiled pages=%u)\n",           cpu_log(cpu->gen,
209                     "JIT","flushing data structures (compiled pages=%u)\n",
210                   cpu->compiled_pages);                   cpu->compiled_pages);
211           mips64_jit_flush(cpu,0);           mips64_jit_flush(cpu,0);
212        } else {        } else {
213           count = mips64_jit_flush(cpu,100);           count = mips64_jit_flush(cpu,100);
214           cpu_log(cpu,"JIT","partial JIT flush (count=%u)\n",count);           cpu_log(cpu->gen,"JIT","partial JIT flush (count=%u)\n",count);
215    
216           if (!cpu->exec_page_free_list)           if (!cpu->exec_page_free_list)
217              mips64_jit_flush(cpu,0);              mips64_jit_flush(cpu,0);
# Line 238  static inline void exec_page_free(cpu_mi Line 240  static inline void exec_page_free(cpu_mi
240  }  }
241    
242  /* Find the JIT code emitter for the specified MIPS instruction */  /* Find the JIT code emitter for the specified MIPS instruction */
243  struct insn_tag *insn_tag_find(mips_insn_t ins)  static struct mips64_insn_tag *insn_tag_find(mips_insn_t ins)
244  {  {
245     struct insn_tag *tag = NULL;     struct mips64_insn_tag *tag = NULL;
246     int index;     int index;
247    
248     index = ilt_lookup(ilt,ins);     index = ilt_lookup(ilt,ins);
# Line 249  struct insn_tag *insn_tag_find(mips_insn Line 251  struct insn_tag *insn_tag_find(mips_insn
251  }  }
252    
253  /* Check if the specified MIPS instruction is a jump */  /* Check if the specified MIPS instruction is a jump */
254  struct insn_jump *insn_jump_find(mips_insn_t ins)  static struct mips64_insn_jump *insn_jump_find(mips_insn_t ins)
255  {  {
256     struct insn_jump *jump = NULL;     struct mips64_insn_jump *jump = NULL;
257     int i;     int i;
258    
259     for(i=0;mips64_insn_jumps[i].name;i++)     for(i=0;mips64_insn_jumps[i].name;i++)
# Line 264  struct insn_jump *insn_jump_find(mips_in Line 266  struct insn_jump *insn_jump_find(mips_in
266  }  }
267    
268  /* Fetch a MIPS instruction */  /* Fetch a MIPS instruction */
269  static forced_inline mips_insn_t insn_fetch(insn_block_t *b)  static forced_inline mips_insn_t insn_fetch(mips64_jit_tcb_t *b)
270  {  {
271     return(vmtoh32(b->mips_code[b->mips_trans_pos]));     return(vmtoh32(b->mips_code[b->mips_trans_pos]));
272  }  }
273    
274  /* Emit a breakpoint if necessary */  /* Emit a breakpoint if necessary */
275  #if BREAKPOINT_ENABLE  #if BREAKPOINT_ENABLE
276  static void insn_emit_breakpoint(cpu_mips_t *cpu,insn_block_t *b)  static void insn_emit_breakpoint(cpu_mips_t *cpu,mips64_jit_tcb_t *b)
277  {  {
278     m_uint64_t pc;     m_uint64_t pc;
279     int i;     int i;
# Line 286  static void insn_emit_breakpoint(cpu_mip Line 288  static void insn_emit_breakpoint(cpu_mip
288  }  }
289  #endif /* BREAKPOINT_ENABLE */  #endif /* BREAKPOINT_ENABLE */
290    
291    /* Get host pointer for the physical address */
292    static inline void *physmem_get_hptr(vm_instance_t *vm,m_uint64_t paddr,
293                                         u_int op_size,u_int op_type,
294                                         m_uint64_t *data)
295    {
296       struct vdevice *dev;
297       m_uint32_t offset;
298       void *ptr;
299       int cow;
300    
301       if (!(dev = dev_lookup(vm,paddr,FALSE)))
302          return NULL;
303    
304       if (dev->flags & VDEVICE_FLAG_SPARSE) {
305          ptr = (void *)dev_sparse_get_host_addr(vm,dev,paddr,op_type,&cow);
306          if (!ptr) return NULL;
307    
308          return(ptr + (paddr & VM_PAGE_IMASK));
309       }
310    
311       if ((dev->host_addr != 0) && !(dev->flags & VDEVICE_FLAG_NO_MTS_MMAP))
312          return((void *)dev->host_addr + (paddr - dev->phys_addr));
313    
314       if (op_size == 0)
315          return NULL;
316    
317       offset = paddr - dev->phys_addr;
318       return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data));
319    }
320    
321  /* Fetch a MIPS instruction and emit corresponding translated code */  /* Fetch a MIPS instruction and emit corresponding translated code */
322  struct insn_tag *insn_fetch_and_emit(cpu_mips_t *cpu,insn_block_t *block,  struct mips64_insn_tag *mips64_jit_fetch_and_emit(cpu_mips_t *cpu,
323                                       int delay_slot)                                                    mips64_jit_tcb_t *block,
324                                                      int delay_slot)
325  {  {
326     struct insn_tag *tag;     struct mips64_insn_tag *tag;
327     mips_insn_t code;     mips_insn_t code;
328    
329     code = insn_fetch(block);     code = insn_fetch(block);
330     tag = insn_tag_find(code);     tag = insn_tag_find(code);
331     assert(tag);     assert(tag);
332      
333       /* Branch-delay slot is in another page: slow exec */
334       if ((block->mips_trans_pos == (MIPS_INSN_PER_PAGE-1)) && !tag->delay_slot) {
335          block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;
336    
337          mips64_set_pc(block,block->start_pc + (block->mips_trans_pos << 2));
338          mips64_emit_single_step(block,code);
339          mips64_jit_tcb_push_epilog(block);
340          block->mips_trans_pos++;
341          return tag;
342       }
343    
344     if (delay_slot && !tag->delay_slot) {     if (delay_slot && !tag->delay_slot) {
345        mips64_emit_invalid_delay_slot(block);        mips64_emit_invalid_delay_slot(block);
346        return NULL;        return NULL;
347     }     }
348    
349     if (!delay_slot) {     if (!delay_slot)
350        block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;        block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;
    }  
351    
352     if (delay_slot != 2)     if (delay_slot != 2)
353        block->mips_trans_pos++;        block->mips_trans_pos++;
# Line 331  struct insn_tag *insn_fetch_and_emit(cpu Line 374  struct insn_tag *insn_fetch_and_emit(cpu
374  }  }
375    
376  /* Add end of JIT block */  /* Add end of JIT block */
377  void insn_block_add_end(insn_block_t *b)  static void mips64_jit_tcb_add_end(mips64_jit_tcb_t *b)
378  {  {
379     mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));     mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));
380     insn_block_push_epilog(b);     mips64_jit_tcb_push_epilog(b);
381  }  }
382    
383  /* Record a patch to apply in a compiled block */  /* Record a patch to apply in a compiled block */
384  int insn_block_record_patch(insn_block_t *block,u_char *jit_ptr,  int mips64_jit_tcb_record_patch(mips64_jit_tcb_t *block,u_char *jit_ptr,
385                              m_uint64_t vaddr)                                  m_uint64_t vaddr)
386  {  {
387     struct insn_patch_table *ipt = block->patch_table;     struct mips64_jit_patch_table *ipt = block->patch_table;
388     struct insn_patch *patch;     struct mips64_insn_patch *patch;
389    
390     /* pc must be 32-bit aligned */     /* pc must be 32-bit aligned */
391     if (vaddr & 0x03) {     if (vaddr & 0x03) {
# Line 352  int insn_block_record_patch(insn_block_t Line 395  int insn_block_record_patch(insn_block_t
395        return(-1);        return(-1);
396     }     }
397    
398     if (!ipt || (ipt->cur_patch >= INSN_PATCH_TABLE_SIZE))     if (!ipt || (ipt->cur_patch >= MIPS64_INSN_PATCH_TABLE_SIZE))
399     {     {
400        /* full table or no table, create a new one */        /* full table or no table, create a new one */
401        ipt = malloc(sizeof(*ipt));        ipt = malloc(sizeof(*ipt));
402        if (!ipt) {        if (!ipt) {
403           fprintf(stderr,"%% Unable to create patch table.\n");           fprintf(stderr,"Block 0x%8.8llx: unable to create patch table.\n",
404                     block->start_pc);
405           return(-1);           return(-1);
406        }        }
407    
# Line 379  int insn_block_record_patch(insn_block_t Line 423  int insn_block_record_patch(insn_block_t
423  }  }
424    
425  /* Apply all patches */  /* Apply all patches */
426  int insn_block_apply_patches(cpu_mips_t *cpu,insn_block_t *block)  static int mips64_jit_tcb_apply_patches(cpu_mips_t *cpu,
427                                            mips64_jit_tcb_t *block)
428  {  {
429     struct insn_patch_table *ipt;     struct mips64_jit_patch_table *ipt;
430     struct insn_patch *patch;     struct mips64_insn_patch *patch;
431     u_char *jit_dst;     u_char *jit_dst;
432     int i;     int i;
433    
# Line 390  int insn_block_apply_patches(cpu_mips_t Line 435  int insn_block_apply_patches(cpu_mips_t
435        for(i=0;i<ipt->cur_patch;i++)        for(i=0;i<ipt->cur_patch;i++)
436        {        {
437           patch = &ipt->patches[i];           patch = &ipt->patches[i];
438           jit_dst = insn_block_get_jit_ptr(block,patch->mips_pc);           jit_dst = mips64_jit_tcb_get_host_ptr(block,patch->mips_pc);
439    
440           if (jit_dst) {           if (jit_dst) {
441  #if DEBUG_BLOCK_PATCH  #if DEBUG_BLOCK_PATCH
# Line 398  int insn_block_apply_patches(cpu_mips_t Line 443  int insn_block_apply_patches(cpu_mips_t
443                     "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",                     "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",
444                     block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);                     block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);
445  #endif  #endif
446              insn_block_set_patch(patch->jit_insn,jit_dst);              mips64_jit_tcb_set_patch(patch->jit_insn,jit_dst);
447           }           }
448        }        }
449    
# Line 406  int insn_block_apply_patches(cpu_mips_t Line 451  int insn_block_apply_patches(cpu_mips_t
451  }  }
452    
453  /* Free the patch table */  /* Free the patch table */
454  static void insn_block_free_patches(insn_block_t *block)  static void mips64_jit_tcb_free_patches(mips64_jit_tcb_t *block)
455  {  {
456     struct insn_patch_table *p,*next;     struct mips64_jit_patch_table *p,*next;
457    
458     for(p=block->patch_table;p;p=next) {     for(p=block->patch_table;p;p=next) {
459        next = p->next;        next = p->next;
# Line 419  static void insn_block_free_patches(insn Line 464  static void insn_block_free_patches(insn
464  }  }
465    
466  /* Adjust the JIT buffer if its size is not sufficient */  /* Adjust the JIT buffer if its size is not sufficient */
467  int insn_block_adjust_jit_buffer(cpu_mips_t *cpu,insn_block_t *block)  static int mips64_jit_tcb_adjust_buffer(cpu_mips_t *cpu,
468                                            mips64_jit_tcb_t *block)
469  {  {
470     insn_exec_page_t *new_buffer;     insn_exec_page_t *new_buffer;
471    
# Line 430  int insn_block_adjust_jit_buffer(cpu_mip Line 476  int insn_block_adjust_jit_buffer(cpu_mip
476     printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);     printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);
477  #endif  #endif
478    
479     if (block->jit_chunk_pos >= INSN_MAX_CHUNKS) {     if (block->jit_chunk_pos >= MIPS_JIT_MAX_CHUNKS) {
480        fprintf(stderr,"Block 0x%llx: too many JIT chunks.\n",block->start_pc);        fprintf(stderr,"Block 0x%llx: too many JIT chunks.\n",block->start_pc);
481        return(-1);        return(-1);
482     }     }
# Line 443  int insn_block_adjust_jit_buffer(cpu_mip Line 489  int insn_block_adjust_jit_buffer(cpu_mip
489     block->jit_buffer = new_buffer;     block->jit_buffer = new_buffer;
490    
491     /* jump to the new exec page (link) */     /* jump to the new exec page (link) */
492     insn_block_set_jump(block->jit_ptr,new_buffer->ptr);     mips64_jit_tcb_set_jump(block->jit_ptr,new_buffer->ptr);
493     block->jit_ptr = new_buffer->ptr;     block->jit_ptr = new_buffer->ptr;
494     return(0);     return(0);
495  }  }
496    
497  /* Allocate an instruction block */  /* Allocate an instruction block */
498  static inline insn_block_t *insn_block_alloc(cpu_mips_t *cpu)  static inline mips64_jit_tcb_t *mips64_jit_tcb_alloc(cpu_mips_t *cpu)
499  {  {
500     insn_block_t *p;     mips64_jit_tcb_t *p;
501    
502     if (cpu->insn_block_free_list) {     if (cpu->tcb_free_list) {
503        p = cpu->insn_block_free_list;        p = cpu->tcb_free_list;
504        cpu->insn_block_free_list = p->next;        cpu->tcb_free_list = p->next;
505     } else {     } else {
506        if (!(p = malloc(sizeof(*p))))        if (!(p = malloc(sizeof(*p))))
507           return NULL;           return NULL;
# Line 466  static inline insn_block_t *insn_block_a Line 512  static inline insn_block_t *insn_block_a
512  }  }
513    
514  /* Free an instruction block */  /* Free an instruction block */
515  void insn_block_free(cpu_mips_t *cpu,insn_block_t *block,int list_removal)  void mips64_jit_tcb_free(cpu_mips_t *cpu,mips64_jit_tcb_t *block,
516                             int list_removal)
517  {  {
518     int i;     int i;
519    
# Line 476  void insn_block_free(cpu_mips_t *cpu,ins Line 523  void insn_block_free(cpu_mips_t *cpu,ins
523           if (block->next)           if (block->next)
524              block->next->prev = block->prev;              block->next->prev = block->prev;
525           else           else
526              cpu->insn_block_last = block->prev;              cpu->tcb_last = block->prev;
527    
528           if (block->prev)           if (block->prev)
529              block->prev->next = block->next;              block->prev->next = block->next;
530           else           else
531              cpu->insn_block_list = block->next;              cpu->tcb_list = block->next;
532        }        }
533    
534        /* Free the patch tables */        /* Free the patch tables */
535        insn_block_free_patches(block);        mips64_jit_tcb_free_patches(block);
536    
537        /* Free code pages */        /* Free code pages */
538        for(i=0;i<INSN_MAX_CHUNKS;i++)        for(i=0;i<MIPS_JIT_MAX_CHUNKS;i++)
539           exec_page_free(cpu,block->jit_chunks[i]);           exec_page_free(cpu,block->jit_chunks[i]);
540    
541        /* Free the current JIT buffer */        /* Free the current JIT buffer */
# Line 498  void insn_block_free(cpu_mips_t *cpu,ins Line 545  void insn_block_free(cpu_mips_t *cpu,ins
545        free(block->jit_insn_ptr);        free(block->jit_insn_ptr);
546    
547        /* Make the block return to the free list */        /* Make the block return to the free list */
548        block->next = cpu->insn_block_free_list;        block->next = cpu->tcb_free_list;
549        cpu->insn_block_free_list = block;        cpu->tcb_free_list = block;
550     }     }
551  }  }
552    
553  /* Create an instruction block */  /* Create an instruction block */
554  static insn_block_t *insn_block_create(cpu_mips_t *cpu,m_uint64_t vaddr)  static mips64_jit_tcb_t *mips64_jit_tcb_create(cpu_mips_t *cpu,
555                                                   m_uint64_t vaddr)
556  {  {
557     insn_block_t *block = NULL;     mips64_jit_tcb_t *block = NULL;
558    
559     if (!(block = insn_block_alloc(cpu)))     if (!(block = mips64_jit_tcb_alloc(cpu)))
560        goto err_block_alloc;        goto err_block_alloc;
561    
562     block->start_pc = vaddr;     block->start_pc = vaddr;
# Line 533  static insn_block_t *insn_block_create(c Line 581  static insn_block_t *insn_block_create(c
581    
582   err_lookup:   err_lookup:
583   err_jit_alloc:   err_jit_alloc:
584     insn_block_free(cpu,block,FALSE);     mips64_jit_tcb_free(cpu,block,FALSE);
585   err_block_alloc:   err_block_alloc:
586     fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n",     fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n",
587             vaddr);             vaddr);
# Line 541  static insn_block_t *insn_block_create(c Line 589  static insn_block_t *insn_block_create(c
589  }  }
590    
591  /* Compile a MIPS instruction page */  /* Compile a MIPS instruction page */
592  static inline insn_block_t *insn_page_compile(cpu_mips_t *cpu,m_uint64_t vaddr)  static inline
593    mips64_jit_tcb_t *mips64_jit_tcb_compile(cpu_mips_t *cpu,m_uint64_t vaddr)
594  {    {  
595       mips64_jit_tcb_t *block;
596       struct mips64_insn_tag *tag;
597     m_uint64_t page_addr;     m_uint64_t page_addr;
    insn_block_t *block;  
    struct insn_tag *tag;  
598     size_t len;     size_t len;
599    
600     page_addr = vaddr & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;     page_addr = vaddr & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;
601    
602     if (unlikely(!(block = insn_block_create(cpu,page_addr)))) {     if (unlikely(!(block = mips64_jit_tcb_create(cpu,page_addr)))) {
603        fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");        fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");
604        return NULL;        return NULL;
605     }     }
# Line 566  static inline insn_block_t *insn_page_co Line 615  static inline insn_block_t *insn_page_co
615     /* Emit native code for each instruction */     /* Emit native code for each instruction */
616     block->mips_trans_pos = 0;     block->mips_trans_pos = 0;
617    
618     while(block->mips_trans_pos < (MIPS_MIN_PAGE_SIZE/sizeof(mips_insn_t)))     while(block->mips_trans_pos < MIPS_INSN_PER_PAGE)
619     {     {
620        if (unlikely(!(tag = insn_fetch_and_emit(cpu,block,0)))) {        if (unlikely(!(tag = mips64_jit_fetch_and_emit(cpu,block,0)))) {
621           fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");           fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");
622           goto error;           goto error;
623        }        }
# Line 578  static inline insn_block_t *insn_page_co Line 627  static inline insn_block_t *insn_page_co
627               block->start_pc,tag->mask,tag->value);               block->start_pc,tag->mask,tag->value);
628  #endif  #endif
629    
630        insn_block_adjust_jit_buffer(cpu,block);        mips64_jit_tcb_adjust_buffer(cpu,block);
631     }     }
632    
633     insn_block_add_end(block);     mips64_jit_tcb_add_end(block);
634     insn_block_apply_patches(cpu,block);     mips64_jit_tcb_apply_patches(cpu,block);
635     insn_block_free_patches(block);     mips64_jit_tcb_free_patches(block);
636    
637     /* Add the block to the linked list */     /* Add the block to the linked list */
638     block->next = cpu->insn_block_list;     block->next = cpu->tcb_list;
639     block->prev = NULL;     block->prev = NULL;
640    
641     if (cpu->insn_block_list)     if (cpu->tcb_list)
642        cpu->insn_block_list->prev = block;        cpu->tcb_list->prev = block;
643     else     else
644        cpu->insn_block_last = block;        cpu->tcb_last = block;
645    
646     cpu->insn_block_list = block;     cpu->tcb_list = block;
647        
648     cpu->compiled_pages++;     cpu->compiled_pages++;
649     return block;     return block;
650    
651   error:   error:
652     insn_block_free(cpu,block,FALSE);     mips64_jit_tcb_free(cpu,block,FALSE);
653     return NULL;     return NULL;
654  }  }
655    
656  /* Run a compiled MIPS instruction block */  /* Run a compiled MIPS instruction block */
657  static forced_inline void insn_block_run(cpu_mips_t *cpu,insn_block_t *block)  static forced_inline
658    void mips64_jit_tcb_run(cpu_mips_t *cpu,mips64_jit_tcb_t *block)
659  {  {
660  #if DEBUG_SYM_TREE  #if DEBUG_SYM_TREE
661     struct symbol *sym = NULL;     struct symbol *sym = NULL;
# Line 613  static forced_inline void insn_block_run Line 663  static forced_inline void insn_block_run
663  #endif  #endif
664    
665     if (unlikely(cpu->pc & 0x03)) {     if (unlikely(cpu->pc & 0x03)) {
666        fprintf(stderr,"insn_block_run: Invalid PC 0x%llx.\n",cpu->pc);        fprintf(stderr,"mips64_jit_tcb_run: Invalid PC 0x%llx.\n",cpu->pc);
667        mips64_dump_regs(cpu);        mips64_dump_regs(cpu->gen);
668        tlb_dump(cpu);              mips64_tlb_dump(cpu->gen);
669        cpu_stop(cpu);        cpu_stop(cpu->gen);
670        return;        return;
671     }     }
672    
# Line 624  static forced_inline void insn_block_run Line 674  static forced_inline void insn_block_run
674     if (cpu->sym_trace && cpu->sym_tree)     if (cpu->sym_trace && cpu->sym_tree)
675     {     {
676        if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {        if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {
677           cpu_log(cpu,"insn_block_run(start)",           cpu_log(cpu,"mips64_jit_tcb_run(start)",
678                   "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "                   "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "
679                   "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",                   "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",
680                   sym->name, cpu->pc, cpu->gpr[MIPS_GPR_RA],                   sym->name, cpu->pc, cpu->gpr[MIPS_GPR_RA],
# Line 636  static forced_inline void insn_block_run Line 686  static forced_inline void insn_block_run
686  #endif  #endif
687    
688     /* Execute JIT compiled code */     /* Execute JIT compiled code */
689     insn_block_exec_jit_code(cpu,block);     mips64_jit_tcb_exec(cpu,block);
690    
691  #if DEBUG_SYM_TREE  #if DEBUG_SYM_TREE
692     if (mark) {     if (mark) {
693        cpu_log(cpu,"insn_block_run(end)","%s, v0 = 0x%llx\n",        cpu_log(cpu,"mips64_jit_tcb_run(end)","%s, v0 = 0x%llx\n",
694                sym->name,cpu->gpr[MIPS_GPR_V0]);                sym->name,cpu->gpr[MIPS_GPR_V0]);
695     }     }
696  #endif  #endif
697  }  }
698    
699  /* Check if the specified address belongs to the specified block */  /* Check if the specified address belongs to the specified block */
700  int insn_block_local_addr(insn_block_t *block,m_uint64_t vaddr,  int mips64_jit_tcb_local_addr(mips64_jit_tcb_t *block,m_uint64_t vaddr,
701                            u_char **jit_addr)                                u_char **jit_addr)
702  {  {
703     if ((vaddr >= block->start_pc) &&     if ((vaddr >= block->start_pc) &&
704         ((vaddr - block->start_pc) < MIPS_MIN_PAGE_SIZE))         ((vaddr - block->start_pc) < MIPS_MIN_PAGE_SIZE))
705     {     {
706        *jit_addr = insn_block_get_jit_ptr(block,vaddr);        *jit_addr = mips64_jit_tcb_get_host_ptr(block,vaddr);
707        return(1);        return(1);
708     }     }
709    
# Line 661  int insn_block_local_addr(insn_block_t * Line 711  int insn_block_local_addr(insn_block_t *
711  }  }
712    
713  /* Check if PC register matches the compiled block virtual address */  /* Check if PC register matches the compiled block virtual address */
714  static forced_inline int insn_block_match(cpu_mips_t *cpu,insn_block_t *block)  static forced_inline
715    int mips64_jit_tcb_match(cpu_mips_t *cpu,mips64_jit_tcb_t *block)
716  {  {
717     m_uint64_t vpage;     m_uint64_t vpage;
718    
# Line 669  static forced_inline int insn_block_matc Line 720  static forced_inline int insn_block_matc
720     return(block->start_pc == vpage);     return(block->start_pc == vpage);
721  }  }
722    
723  /* Execute a compiled MIPS code */  /* Execute compiled MIPS code */
724  void *insn_block_execute(cpu_mips_t *cpu)  void *mips64_jit_run_cpu(cpu_gen_t *gen)
725  {    {    
726       cpu_mips_t *cpu = CPU_MIPS64(gen);
727     pthread_t timer_irq_thread;     pthread_t timer_irq_thread;
728     insn_block_t *block;     mips64_jit_tcb_t *block;
729     m_uint32_t phys_page;     m_uint32_t phys_page;
730     int timer_irq_check = 0;     int timer_irq_check = 0;
731    
# Line 682  void *insn_block_execute(cpu_mips_t *cpu Line 734  void *insn_block_execute(cpu_mips_t *cpu
734     {     {
735        fprintf(stderr,        fprintf(stderr,
736                "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",                "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",
737                cpu->vm->name,cpu->id);                cpu->vm->name,gen->id);
738        cpu_stop(cpu);        cpu_stop(cpu->gen);
739        return NULL;        return NULL;
740     }     }
741    
742     cpu->cpu_thread_running = TRUE;     gen->cpu_thread_running = TRUE;
743    
744   start_cpu:     start_cpu:  
745     cpu->idle_count = 0;     gen->idle_count = 0;
746    
747     for(;;) {     for(;;) {
748        if (unlikely(cpu->state != MIPS_CPU_RUNNING))        if (unlikely(gen->state != CPU_STATE_RUNNING))
749           break;           break;
750    
751  #if DEBUG_BLOCK_PERF_CNT  #if DEBUG_BLOCK_PERF_CNT
# Line 701  void *insn_block_execute(cpu_mips_t *cpu Line 753  void *insn_block_execute(cpu_mips_t *cpu
753  #endif  #endif
754        /* Handle virtual idle loop */        /* Handle virtual idle loop */
755        if (unlikely(cpu->pc == cpu->idle_pc)) {        if (unlikely(cpu->pc == cpu->idle_pc)) {
756           if (++cpu->idle_count == cpu->idle_max) {           if (++gen->idle_count == gen->idle_max) {
757              mips64_idle_loop(cpu);              cpu_idle_loop(gen);
758              cpu->idle_count = 0;              gen->idle_count = 0;
759           }           }
760        }        }
761    
# Line 721  void *insn_block_execute(cpu_mips_t *cpu Line 773  void *insn_block_execute(cpu_mips_t *cpu
773        /* Get the physical page address corresponding to PC register */        /* Get the physical page address corresponding to PC register */
774        if (unlikely(cpu->translate(cpu,cpu->pc,&phys_page))) {        if (unlikely(cpu->translate(cpu,cpu->pc,&phys_page))) {
775           fprintf(stderr,"VM '%s': no physical page for CPU%u PC=0x%llx\n",           fprintf(stderr,"VM '%s': no physical page for CPU%u PC=0x%llx\n",
776                   cpu->vm->name,cpu->id,cpu->pc);                   cpu->vm->name,gen->id,cpu->pc);
777           cpu_stop(cpu);           cpu_stop(gen);
778           break;           break;
779        }        }
780    
781        block = cpu->exec_phys_map[phys_page];        block = cpu->exec_phys_map[phys_page];
782    
783        /* No block found, compile the page */        /* No block found, compile the page */
784        if (unlikely(!block) || unlikely(!insn_block_match(cpu,block)))        if (unlikely(!block) || unlikely(!mips64_jit_tcb_match(cpu,block)))
785        {        {
786           if (block != NULL) {           if (block != NULL) {
787              insn_block_free(cpu,block,TRUE);              mips64_jit_tcb_free(cpu,block,TRUE);
788              cpu->exec_phys_map[phys_page] = NULL;              cpu->exec_phys_map[phys_page] = NULL;
789           }           }
790    
791           block = insn_page_compile(cpu,cpu->pc);           block = mips64_jit_tcb_compile(cpu,cpu->pc);
792           if (unlikely(!block)) {           if (unlikely(!block)) {
793              fprintf(stderr,              fprintf(stderr,
794                      "VM '%s': unable to compile block for CPU%u PC=0x%llx\n",                      "VM '%s': unable to compile block for CPU%u PC=0x%llx\n",
795                      cpu->vm->name,cpu->id,cpu->pc);                      cpu->vm->name,gen->id,cpu->pc);
796              cpu_stop(cpu);              cpu_stop(gen);
797              break;              break;
798           }           }
799    
# Line 753  void *insn_block_execute(cpu_mips_t *cpu Line 805  void *insn_block_execute(cpu_mips_t *cpu
805        block->tm_last_use = jit_jiffies++;        block->tm_last_use = jit_jiffies++;
806  #endif  #endif
807        block->acc_count++;        block->acc_count++;
808        insn_block_run(cpu,block);        mips64_jit_tcb_run(cpu,block);
809     }     }
810                
811     if (!cpu->pc) {     if (!cpu->pc) {
812        cpu_stop(cpu);        cpu_stop(gen);
813        cpu_log(cpu,"JIT","PC=0, halting CPU.\n");        cpu_log(gen,"JIT","PC=0, halting CPU.\n");
814     }     }
815    
816     /* Check regularly if the CPU has been restarted */     /* Check regularly if the CPU has been restarted */
817     while(cpu->cpu_thread_running) {     while(gen->cpu_thread_running) {
818        cpu->seq_state++;        gen->seq_state++;
819    
820        switch(cpu->state) {        switch(gen->state) {
821           case MIPS_CPU_RUNNING:           case CPU_STATE_RUNNING:
822              cpu->state = MIPS_CPU_RUNNING;              gen->state = CPU_STATE_RUNNING;
823              goto start_cpu;              goto start_cpu;
824    
825           case MIPS_CPU_HALTED:           case CPU_STATE_HALTED:
826              cpu->cpu_thread_running = FALSE;              gen->cpu_thread_running = FALSE;
827              pthread_join(timer_irq_thread,NULL);              pthread_join(timer_irq_thread,NULL);
828              break;              break;
829        }        }

Legend:
Removed from v.6  
changed lines
  Added in v.7

  ViewVC Help
Powered by ViewVC 1.1.26