/[dynamips]/trunk/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 /trunk/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 trunk/mips64_jit.c revision 12 by dpavlin, Sat Oct 6 16:45:40 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    
19  #include ARCH_INC_FILE  #include "sbox.h"
   
 #include "rbtree.h"  
 #include "cp0.h"  
 #include "memory.h"  
20  #include "cpu.h"  #include "cpu.h"
21  #include "device.h"  #include "device.h"
22  #include "mips64.h"  #include "mips64.h"
23    #include "mips64_cp0.h"
24  #include "mips64_exec.h"  #include "mips64_exec.h"
25    #include "mips64_jit.h"
26  #include "insn_lookup.h"  #include "insn_lookup.h"
27    #include "memory.h"
28  #include "ptask.h"  #include "ptask.h"
29    
30    #include MIPS64_ARCH_INC_FILE
31    
32  #if DEBUG_BLOCK_TIMESTAMP  #if DEBUG_BLOCK_TIMESTAMP
33  static volatile m_uint64_t jit_jiffies = 0;  static volatile m_uint64_t jit_jiffies = 0;
34  #endif  #endif
35    
36  /* MIPS jump instructions for block scan */  /* MIPS jump instructions for block scan */
37  struct insn_jump mips64_insn_jumps[] = {  struct mips64_insn_jump mips64_insn_jumps[] = {
38     { "b"       , 0xffff0000, 0x10000000, 16, 1 },     { "b"       , 0xffff0000, 0x10000000, 16, 1 },
39     { "bal"     , 0xffff0000, 0x04110000, 16, 1 },     { "bal"     , 0xffff0000, 0x04110000, 16, 1 },
40     { "beq"     , 0xfc000000, 0x10000000, 16, 1 },     { "beq"     , 0xfc000000, 0x10000000, 16, 1 },
# Line 64  static void *mips64_jit_get_insn(int ind Line 65  static void *mips64_jit_get_insn(int ind
65     return(&mips64_insn_tags[index]);     return(&mips64_insn_tags[index]);
66  }  }
67    
68  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)
69  {  {
70     return((value & tag->mask) == (tag->value & 0xFFFF));     return((value & tag->mask) == (tag->value & 0xFFFF));
71  }  }
72    
73  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)
74  {  {
75     return((value & (tag->mask >> 16)) == (tag->value >> 16));     return((value & (tag->mask >> 16)) == (tag->value >> 16));
76  }  }
# Line 82  void mips64_jit_create_ilt(void) Line 83  void mips64_jit_create_ilt(void)
83     for(i=0,count=0;mips64_insn_tags[i].emit;i++)     for(i=0,count=0;mips64_insn_tags[i].emit;i++)
84        count++;        count++;
85    
86     ilt = ilt_create(count,     ilt = ilt_create("mips64j",count,
87                      (ilt_get_insn_cbk_t)mips64_jit_get_insn,                      (ilt_get_insn_cbk_t)mips64_jit_get_insn,
88                      (ilt_check_cbk_t)mips64_jit_chk_lo,                      (ilt_check_cbk_t)mips64_jit_chk_lo,
89                      (ilt_check_cbk_t)mips64_jit_chk_hi);                      (ilt_check_cbk_t)mips64_jit_chk_hi);
# Line 98  int mips64_jit_init(cpu_mips_t *cpu) Line 99  int mips64_jit_init(cpu_mips_t *cpu)
99     int i;     int i;
100    
101     /* Physical mapping for executable pages */     /* Physical mapping for executable pages */
102     len = 1048576 * sizeof(void *);     len = MIPS_JIT_PC_HASH_SIZE * sizeof(void *);
103     cpu->exec_phys_map = m_memalign(4096,len);     cpu->exec_blk_map = m_memalign(4096,len);
104     memset(cpu->exec_phys_map,0,len);     memset(cpu->exec_blk_map,0,len);
105    
106     /* Get area size */     /* Get area size */
107     if (!(area_size = cpu->vm->exec_area_size))     if (!(area_size = cpu->vm->exec_area_size))
# Line 141  int mips64_jit_init(cpu_mips_t *cpu) Line 142  int mips64_jit_init(cpu_mips_t *cpu)
142     }     }
143    
144     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",
145            cpu->id,(u_long)(cpu->exec_page_area_size / 1048576),            cpu->gen->id,
146              (u_long)(cpu->exec_page_area_size / 1048576),
147            (u_long)cpu->exec_page_count,MIPS_JIT_BUFSIZE / 1024);            (u_long)cpu->exec_page_count,MIPS_JIT_BUFSIZE / 1024);
148     return(0);     return(0);
149  }  }
# Line 149  int mips64_jit_init(cpu_mips_t *cpu) Line 151  int mips64_jit_init(cpu_mips_t *cpu)
151  /* Flush the JIT */  /* Flush the JIT */
152  u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold)  u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold)
153  {  {
154     insn_block_t *p,*next;     mips64_jit_tcb_t *p,*next;
155       m_uint32_t pc_hash;
156     u_int count = 0;     u_int count = 0;
157    
158     if (!threshold)     if (!threshold)
159        threshold = (u_int)(-1);  /* UINT_MAX not defined everywhere */        threshold = (u_int)(-1);  /* UINT_MAX not defined everywhere */
160    
161     for(p=cpu->insn_block_list;p;p=next) {     for(p=cpu->tcb_list;p;p=next) {
162        next = p->next;        next = p->next;
163    
164        if (p->acc_count <= threshold) {        if (p->acc_count <= threshold) {
165           cpu->exec_phys_map[p->phys_page] = NULL;           pc_hash = mips64_jit_get_pc_hash(p->start_pc);
166           insn_block_free(cpu,p,TRUE);           cpu->exec_blk_map[pc_hash] = NULL;
167             mips64_jit_tcb_free(cpu,p,TRUE);
168           count++;           count++;
169        }        }
170     }     }
# Line 172  u_int mips64_jit_flush(cpu_mips_t *cpu,u Line 176  u_int mips64_jit_flush(cpu_mips_t *cpu,u
176  /* Shutdown the JIT */  /* Shutdown the JIT */
177  void mips64_jit_shutdown(cpu_mips_t *cpu)  void mips64_jit_shutdown(cpu_mips_t *cpu)
178  {    {  
179     insn_block_t *p,*next;     mips64_jit_tcb_t *p,*next;
180    
181     /* Flush the JIT */     /* Flush the JIT */
182     mips64_jit_flush(cpu,0);     mips64_jit_flush(cpu,0);
183    
184     /* Free the instruction blocks */     /* Free the instruction blocks */
185     for(p=cpu->insn_block_free_list;p;p=next) {     for(p=cpu->tcb_free_list;p;p=next) {
186        next = p->next;        next = p->next;
187        free(p);        free(p);
188     }     }
# Line 191  void mips64_jit_shutdown(cpu_mips_t *cpu Line 195  void mips64_jit_shutdown(cpu_mips_t *cpu
195     free(cpu->exec_page_array);     free(cpu->exec_page_array);
196    
197     /* Free physical mapping for executable pages */     /* Free physical mapping for executable pages */
198     free(cpu->exec_phys_map);       free(cpu->exec_blk_map);  
199  }  }
200    
201  /* Allocate an exec page */  /* Allocate an exec page */
# Line 204  static inline insn_exec_page_t *exec_pag Line 208  static inline insn_exec_page_t *exec_pag
208     if (unlikely(!cpu->exec_page_free_list))     if (unlikely(!cpu->exec_page_free_list))
209     {     {
210        if (cpu->jit_flush_method) {        if (cpu->jit_flush_method) {
211           cpu_log(cpu,"JIT","flushing data structures (compiled pages=%u)\n",           cpu_log(cpu->gen,
212                     "JIT","flushing data structures (compiled pages=%u)\n",
213                   cpu->compiled_pages);                   cpu->compiled_pages);
214           mips64_jit_flush(cpu,0);           mips64_jit_flush(cpu,0);
215        } else {        } else {
216           count = mips64_jit_flush(cpu,100);           count = mips64_jit_flush(cpu,100);
217           cpu_log(cpu,"JIT","partial JIT flush (count=%u)\n",count);           cpu_log(cpu->gen,"JIT","partial JIT flush (count=%u)\n",count);
218    
219           if (!cpu->exec_page_free_list)           if (!cpu->exec_page_free_list)
220              mips64_jit_flush(cpu,0);              mips64_jit_flush(cpu,0);
# Line 238  static inline void exec_page_free(cpu_mi Line 243  static inline void exec_page_free(cpu_mi
243  }  }
244    
245  /* Find the JIT code emitter for the specified MIPS instruction */  /* Find the JIT code emitter for the specified MIPS instruction */
246  struct insn_tag *insn_tag_find(mips_insn_t ins)  static struct mips64_insn_tag *insn_tag_find(mips_insn_t ins)
247  {  {
248     struct insn_tag *tag = NULL;     struct mips64_insn_tag *tag = NULL;
249     int index;     int index;
250    
251     index = ilt_lookup(ilt,ins);     index = ilt_lookup(ilt,ins);
# Line 249  struct insn_tag *insn_tag_find(mips_insn Line 254  struct insn_tag *insn_tag_find(mips_insn
254  }  }
255    
256  /* Check if the specified MIPS instruction is a jump */  /* Check if the specified MIPS instruction is a jump */
257  struct insn_jump *insn_jump_find(mips_insn_t ins)  static struct mips64_insn_jump *insn_jump_find(mips_insn_t ins)
258  {  {
259     struct insn_jump *jump = NULL;     struct mips64_insn_jump *jump = NULL;
260     int i;     int i;
261    
262     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 269  struct insn_jump *insn_jump_find(mips_in
269  }  }
270    
271  /* Fetch a MIPS instruction */  /* Fetch a MIPS instruction */
272  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)
273  {  {
274     return(vmtoh32(b->mips_code[b->mips_trans_pos]));     return(vmtoh32(b->mips_code[b->mips_trans_pos]));
275  }  }
276    
277  /* Emit a breakpoint if necessary */  /* Emit a breakpoint if necessary */
278  #if BREAKPOINT_ENABLE  #if BREAKPOINT_ENABLE
279  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)
280  {  {
281     m_uint64_t pc;     m_uint64_t pc;
282     int i;     int i;
# Line 286  static void insn_emit_breakpoint(cpu_mip Line 291  static void insn_emit_breakpoint(cpu_mip
291  }  }
292  #endif /* BREAKPOINT_ENABLE */  #endif /* BREAKPOINT_ENABLE */
293    
294    /* Get host pointer for the physical address */
295    static inline void *physmem_get_hptr(vm_instance_t *vm,m_uint64_t paddr,
296                                         u_int op_size,u_int op_type,
297                                         m_uint64_t *data)
298    {
299       struct vdevice *dev;
300       m_uint32_t offset;
301       void *ptr;
302       int cow;
303    
304       if (!(dev = dev_lookup(vm,paddr,FALSE)))
305          return NULL;
306    
307       if (dev->flags & VDEVICE_FLAG_SPARSE) {
308          ptr = (void *)dev_sparse_get_host_addr(vm,dev,paddr,op_type,&cow);
309          if (!ptr) return NULL;
310    
311          return(ptr + (paddr & VM_PAGE_IMASK));
312       }
313    
314       if ((dev->host_addr != 0) && !(dev->flags & VDEVICE_FLAG_NO_MTS_MMAP))
315          return((void *)dev->host_addr + (paddr - dev->phys_addr));
316    
317       if (op_size == 0)
318          return NULL;
319    
320       offset = paddr - dev->phys_addr;
321       return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data));
322    }
323    
324    /* Check if an instruction is in a delay slot or not */
325    int mips64_jit_is_delay_slot(mips64_jit_tcb_t *b,m_uint64_t pc)
326    {  
327       struct mips64_insn_tag *tag;
328       m_uint32_t offset,insn;
329    
330       offset = (pc - b->start_pc) >> 2;
331    
332       if (!offset)
333          return(FALSE);
334    
335       /* Fetch the previous instruction to determine if it is a jump */
336       insn = vmtoh32(b->mips_code[offset-1]);
337       tag = insn_tag_find(insn);
338       assert(tag != NULL);
339       return(!tag->delay_slot);
340    }
341    
342  /* Fetch a MIPS instruction and emit corresponding translated code */  /* Fetch a MIPS instruction and emit corresponding translated code */
343  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,
344                                       int delay_slot)                                                    mips64_jit_tcb_t *block,
345                                                      int delay_slot)
346  {  {
347     struct insn_tag *tag;     struct mips64_insn_tag *tag;
348     mips_insn_t code;     mips_insn_t code;
349    
350     code = insn_fetch(block);     code = insn_fetch(block);
351     tag = insn_tag_find(code);     tag = insn_tag_find(code);
352     assert(tag);     assert(tag);
353      
354       /* Branch-delay slot is in another page: slow exec */
355       if ((block->mips_trans_pos == (MIPS_INSN_PER_PAGE-1)) && !tag->delay_slot) {
356          block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;
357    
358          mips64_set_pc(block,block->start_pc + (block->mips_trans_pos << 2));
359          mips64_emit_single_step(block,code);
360          mips64_jit_tcb_push_epilog(block);
361          block->mips_trans_pos++;
362          return tag;
363       }
364    
365     if (delay_slot && !tag->delay_slot) {     if (delay_slot && !tag->delay_slot) {
366        mips64_emit_invalid_delay_slot(block);        mips64_emit_invalid_delay_slot(block);
367        return NULL;        return NULL;
368     }     }
369    
370     if (!delay_slot) {     if (!delay_slot)
371        block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;        block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;
    }  
372    
373     if (delay_slot != 2)     if (delay_slot != 2)
374        block->mips_trans_pos++;        block->mips_trans_pos++;
# Line 331  struct insn_tag *insn_fetch_and_emit(cpu Line 395  struct insn_tag *insn_fetch_and_emit(cpu
395  }  }
396    
397  /* Add end of JIT block */  /* Add end of JIT block */
398  void insn_block_add_end(insn_block_t *b)  static void mips64_jit_tcb_add_end(mips64_jit_tcb_t *b)
399  {  {
400     mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));     mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));
401     insn_block_push_epilog(b);     mips64_jit_tcb_push_epilog(b);
402  }  }
403    
404  /* Record a patch to apply in a compiled block */  /* Record a patch to apply in a compiled block */
405  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,
406                              m_uint64_t vaddr)                                  m_uint64_t vaddr)
407  {  {
408     struct insn_patch_table *ipt = block->patch_table;     struct mips64_jit_patch_table *ipt = block->patch_table;
409     struct insn_patch *patch;     struct mips64_insn_patch *patch;
410    
411     /* pc must be 32-bit aligned */     /* pc must be 32-bit aligned */
412     if (vaddr & 0x03) {     if (vaddr & 0x03) {
# Line 352  int insn_block_record_patch(insn_block_t Line 416  int insn_block_record_patch(insn_block_t
416        return(-1);        return(-1);
417     }     }
418    
419     if (!ipt || (ipt->cur_patch >= INSN_PATCH_TABLE_SIZE))     if (!ipt || (ipt->cur_patch >= MIPS64_INSN_PATCH_TABLE_SIZE))
420     {     {
421        /* full table or no table, create a new one */        /* full table or no table, create a new one */
422        ipt = malloc(sizeof(*ipt));        ipt = malloc(sizeof(*ipt));
423        if (!ipt) {        if (!ipt) {
424           fprintf(stderr,"%% Unable to create patch table.\n");           fprintf(stderr,"Block 0x%8.8llx: unable to create patch table.\n",
425                     block->start_pc);
426           return(-1);           return(-1);
427        }        }
428    
# Line 379  int insn_block_record_patch(insn_block_t Line 444  int insn_block_record_patch(insn_block_t
444  }  }
445    
446  /* Apply all patches */  /* Apply all patches */
447  int insn_block_apply_patches(cpu_mips_t *cpu,insn_block_t *block)  static int mips64_jit_tcb_apply_patches(cpu_mips_t *cpu,
448                                            mips64_jit_tcb_t *block)
449  {  {
450     struct insn_patch_table *ipt;     struct mips64_jit_patch_table *ipt;
451     struct insn_patch *patch;     struct mips64_insn_patch *patch;
452     u_char *jit_dst;     u_char *jit_dst;
453     int i;     int i;
454    
# Line 390  int insn_block_apply_patches(cpu_mips_t Line 456  int insn_block_apply_patches(cpu_mips_t
456        for(i=0;i<ipt->cur_patch;i++)        for(i=0;i<ipt->cur_patch;i++)
457        {        {
458           patch = &ipt->patches[i];           patch = &ipt->patches[i];
459           jit_dst = insn_block_get_jit_ptr(block,patch->mips_pc);           jit_dst = mips64_jit_tcb_get_host_ptr(block,patch->mips_pc);
460    
461           if (jit_dst) {           if (jit_dst) {
462  #if DEBUG_BLOCK_PATCH  #if DEBUG_BLOCK_PATCH
# Line 398  int insn_block_apply_patches(cpu_mips_t Line 464  int insn_block_apply_patches(cpu_mips_t
464                     "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",                     "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",
465                     block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);                     block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);
466  #endif  #endif
467              insn_block_set_patch(patch->jit_insn,jit_dst);              mips64_jit_tcb_set_patch(patch->jit_insn,jit_dst);
468           }           }
469        }        }
470    
# Line 406  int insn_block_apply_patches(cpu_mips_t Line 472  int insn_block_apply_patches(cpu_mips_t
472  }  }
473    
474  /* Free the patch table */  /* Free the patch table */
475  static void insn_block_free_patches(insn_block_t *block)  static void mips64_jit_tcb_free_patches(mips64_jit_tcb_t *block)
476  {  {
477     struct insn_patch_table *p,*next;     struct mips64_jit_patch_table *p,*next;
478    
479     for(p=block->patch_table;p;p=next) {     for(p=block->patch_table;p;p=next) {
480        next = p->next;        next = p->next;
# Line 419  static void insn_block_free_patches(insn Line 485  static void insn_block_free_patches(insn
485  }  }
486    
487  /* Adjust the JIT buffer if its size is not sufficient */  /* Adjust the JIT buffer if its size is not sufficient */
488  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,
489                                            mips64_jit_tcb_t *block)
490  {  {
491     insn_exec_page_t *new_buffer;     insn_exec_page_t *new_buffer;
492    
# Line 430  int insn_block_adjust_jit_buffer(cpu_mip Line 497  int insn_block_adjust_jit_buffer(cpu_mip
497     printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);     printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);
498  #endif  #endif
499    
500     if (block->jit_chunk_pos >= INSN_MAX_CHUNKS) {     if (block->jit_chunk_pos >= MIPS_JIT_MAX_CHUNKS) {
501        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);
502        return(-1);        return(-1);
503     }     }
# Line 443  int insn_block_adjust_jit_buffer(cpu_mip Line 510  int insn_block_adjust_jit_buffer(cpu_mip
510     block->jit_buffer = new_buffer;     block->jit_buffer = new_buffer;
511    
512     /* jump to the new exec page (link) */     /* jump to the new exec page (link) */
513     insn_block_set_jump(block->jit_ptr,new_buffer->ptr);     mips64_jit_tcb_set_jump(block->jit_ptr,new_buffer->ptr);
514     block->jit_ptr = new_buffer->ptr;     block->jit_ptr = new_buffer->ptr;
515     return(0);     return(0);
516  }  }
517    
518  /* Allocate an instruction block */  /* Allocate an instruction block */
519  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)
520  {  {
521     insn_block_t *p;     mips64_jit_tcb_t *p;
522    
523     if (cpu->insn_block_free_list) {     if (cpu->tcb_free_list) {
524        p = cpu->insn_block_free_list;        p = cpu->tcb_free_list;
525        cpu->insn_block_free_list = p->next;        cpu->tcb_free_list = p->next;
526     } else {     } else {
527        if (!(p = malloc(sizeof(*p))))        if (!(p = malloc(sizeof(*p))))
528           return NULL;           return NULL;
# Line 466  static inline insn_block_t *insn_block_a Line 533  static inline insn_block_t *insn_block_a
533  }  }
534    
535  /* Free an instruction block */  /* Free an instruction block */
536  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,
537                             int list_removal)
538  {  {
539     int i;     int i;
540    
# Line 476  void insn_block_free(cpu_mips_t *cpu,ins Line 544  void insn_block_free(cpu_mips_t *cpu,ins
544           if (block->next)           if (block->next)
545              block->next->prev = block->prev;              block->next->prev = block->prev;
546           else           else
547              cpu->insn_block_last = block->prev;              cpu->tcb_last = block->prev;
548    
549           if (block->prev)           if (block->prev)
550              block->prev->next = block->next;              block->prev->next = block->next;
551           else           else
552              cpu->insn_block_list = block->next;              cpu->tcb_list = block->next;
553        }        }
554    
555        /* Free the patch tables */        /* Free the patch tables */
556        insn_block_free_patches(block);        mips64_jit_tcb_free_patches(block);
557    
558        /* Free code pages */        /* Free code pages */
559        for(i=0;i<INSN_MAX_CHUNKS;i++)        for(i=0;i<MIPS_JIT_MAX_CHUNKS;i++)
560           exec_page_free(cpu,block->jit_chunks[i]);           exec_page_free(cpu,block->jit_chunks[i]);
561    
562        /* Free the current JIT buffer */        /* Free the current JIT buffer */
# Line 498  void insn_block_free(cpu_mips_t *cpu,ins Line 566  void insn_block_free(cpu_mips_t *cpu,ins
566        free(block->jit_insn_ptr);        free(block->jit_insn_ptr);
567    
568        /* Make the block return to the free list */        /* Make the block return to the free list */
569        block->next = cpu->insn_block_free_list;        block->next = cpu->tcb_free_list;
570        cpu->insn_block_free_list = block;        cpu->tcb_free_list = block;
571     }     }
572  }  }
573    
574  /* Create an instruction block */  /* Create an instruction block */
575  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,
576                                                   m_uint64_t vaddr)
577  {  {
578     insn_block_t *block = NULL;     mips64_jit_tcb_t *block = NULL;
579    
580     if (!(block = insn_block_alloc(cpu)))     if (!(block = mips64_jit_tcb_alloc(cpu)))
581        goto err_block_alloc;        goto err_block_alloc;
582    
583     block->start_pc = vaddr;     block->start_pc = vaddr;
# Line 533  static insn_block_t *insn_block_create(c Line 602  static insn_block_t *insn_block_create(c
602    
603   err_lookup:   err_lookup:
604   err_jit_alloc:   err_jit_alloc:
605     insn_block_free(cpu,block,FALSE);     mips64_jit_tcb_free(cpu,block,FALSE);
606   err_block_alloc:   err_block_alloc:
607     fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n",     fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n",
608             vaddr);             vaddr);
# Line 541  static insn_block_t *insn_block_create(c Line 610  static insn_block_t *insn_block_create(c
610  }  }
611    
612  /* Compile a MIPS instruction page */  /* Compile a MIPS instruction page */
613  static inline insn_block_t *insn_page_compile(cpu_mips_t *cpu,m_uint64_t vaddr)  static inline
614    mips64_jit_tcb_t *mips64_jit_tcb_compile(cpu_mips_t *cpu,m_uint64_t vaddr)
615  {    {  
616       mips64_jit_tcb_t *block;
617       struct mips64_insn_tag *tag;
618     m_uint64_t page_addr;     m_uint64_t page_addr;
    insn_block_t *block;  
    struct insn_tag *tag;  
619     size_t len;     size_t len;
620    
621     page_addr = vaddr & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;     page_addr = vaddr & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;
622    
623     if (unlikely(!(block = insn_block_create(cpu,page_addr)))) {     if (unlikely(!(block = mips64_jit_tcb_create(cpu,page_addr)))) {
624        fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");        fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");
625        return NULL;        return NULL;
626     }     }
# Line 566  static inline insn_block_t *insn_page_co Line 636  static inline insn_block_t *insn_page_co
636     /* Emit native code for each instruction */     /* Emit native code for each instruction */
637     block->mips_trans_pos = 0;     block->mips_trans_pos = 0;
638    
639     while(block->mips_trans_pos < (MIPS_MIN_PAGE_SIZE/sizeof(mips_insn_t)))     while(block->mips_trans_pos < MIPS_INSN_PER_PAGE)
640     {     {
641        if (unlikely(!(tag = insn_fetch_and_emit(cpu,block,0)))) {        if (unlikely(!(tag = mips64_jit_fetch_and_emit(cpu,block,0)))) {
642           fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");           fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");
643           goto error;           goto error;
644        }        }
# Line 578  static inline insn_block_t *insn_page_co Line 648  static inline insn_block_t *insn_page_co
648               block->start_pc,tag->mask,tag->value);               block->start_pc,tag->mask,tag->value);
649  #endif  #endif
650    
651        insn_block_adjust_jit_buffer(cpu,block);        mips64_jit_tcb_adjust_buffer(cpu,block);
652     }     }
653    
654     insn_block_add_end(block);     mips64_jit_tcb_add_end(block);
655     insn_block_apply_patches(cpu,block);     mips64_jit_tcb_apply_patches(cpu,block);
656     insn_block_free_patches(block);     mips64_jit_tcb_free_patches(block);
657    
658     /* Add the block to the linked list */     /* Add the block to the linked list */
659     block->next = cpu->insn_block_list;     block->next = cpu->tcb_list;
660     block->prev = NULL;     block->prev = NULL;
661    
662     if (cpu->insn_block_list)     if (cpu->tcb_list)
663        cpu->insn_block_list->prev = block;        cpu->tcb_list->prev = block;
664     else     else
665        cpu->insn_block_last = block;        cpu->tcb_last = block;
666    
667     cpu->insn_block_list = block;     cpu->tcb_list = block;
668        
669     cpu->compiled_pages++;     cpu->compiled_pages++;
670     return block;     return block;
671    
672   error:   error:
673     insn_block_free(cpu,block,FALSE);     mips64_jit_tcb_free(cpu,block,FALSE);
674     return NULL;     return NULL;
675  }  }
676    
677  /* Run a compiled MIPS instruction block */  /* Run a compiled MIPS instruction block */
678  static forced_inline void insn_block_run(cpu_mips_t *cpu,insn_block_t *block)  static forced_inline
679    void mips64_jit_tcb_run(cpu_mips_t *cpu,mips64_jit_tcb_t *block)
680  {  {
681  #if DEBUG_SYM_TREE  #if DEBUG_SYM_TREE
682     struct symbol *sym = NULL;     struct symbol *sym = NULL;
# Line 613  static forced_inline void insn_block_run Line 684  static forced_inline void insn_block_run
684  #endif  #endif
685    
686     if (unlikely(cpu->pc & 0x03)) {     if (unlikely(cpu->pc & 0x03)) {
687        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);
688        mips64_dump_regs(cpu);        mips64_dump_regs(cpu->gen);
689        tlb_dump(cpu);              mips64_tlb_dump(cpu->gen);
690        cpu_stop(cpu);        cpu_stop(cpu->gen);
691        return;        return;
692     }     }
693    
# Line 624  static forced_inline void insn_block_run Line 695  static forced_inline void insn_block_run
695     if (cpu->sym_trace && cpu->sym_tree)     if (cpu->sym_trace && cpu->sym_tree)
696     {     {
697        if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {        if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {
698           cpu_log(cpu,"insn_block_run(start)",           cpu_log(cpu,"mips64_jit_tcb_run(start)",
699                   "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "                   "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "
700                   "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",                   "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",
701                   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 707  static forced_inline void insn_block_run
707  #endif  #endif
708    
709     /* Execute JIT compiled code */     /* Execute JIT compiled code */
710     insn_block_exec_jit_code(cpu,block);     mips64_jit_tcb_exec(cpu,block);
711    
712  #if DEBUG_SYM_TREE  #if DEBUG_SYM_TREE
713     if (mark) {     if (mark) {
714        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",
715                sym->name,cpu->gpr[MIPS_GPR_V0]);                sym->name,cpu->gpr[MIPS_GPR_V0]);
716     }     }
717  #endif  #endif
718  }  }
719    
720  /* Check if the specified address belongs to the specified block */  /* Execute compiled MIPS code */
721  int insn_block_local_addr(insn_block_t *block,m_uint64_t vaddr,  void *mips64_jit_run_cpu(cpu_gen_t *gen)
722                            u_char **jit_addr)  {    
723  {     cpu_mips_t *cpu = CPU_MIPS64(gen);
    if ((vaddr >= block->start_pc) &&  
        ((vaddr - block->start_pc) < MIPS_MIN_PAGE_SIZE))  
    {  
       *jit_addr = insn_block_get_jit_ptr(block,vaddr);  
       return(1);  
    }  
   
    return(0);  
 }  
   
 /* Check if PC register matches the compiled block virtual address */  
 static forced_inline int insn_block_match(cpu_mips_t *cpu,insn_block_t *block)  
 {  
    m_uint64_t vpage;  
   
    vpage = cpu->pc & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;  
    return(block->start_pc == vpage);  
 }  
   
 /* Execute a compiled MIPS code */  
 void *insn_block_execute(cpu_mips_t *cpu)  
 {    
724     pthread_t timer_irq_thread;     pthread_t timer_irq_thread;
725     insn_block_t *block;     mips64_jit_tcb_t *block;
    m_uint32_t phys_page;  
726     int timer_irq_check = 0;     int timer_irq_check = 0;
727       m_uint32_t pc_hash;
728    
729     if (pthread_create(&timer_irq_thread,NULL,     if (pthread_create(&timer_irq_thread,NULL,
730                        (void *)mips64_timer_irq_run,cpu))                        (void *)mips64_timer_irq_run,cpu))
731     {     {
732        fprintf(stderr,        fprintf(stderr,
733                "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",                "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",
734                cpu->vm->name,cpu->id);                cpu->vm->name,gen->id);
735        cpu_stop(cpu);        cpu_stop(cpu->gen);
736        return NULL;        return NULL;
737     }     }
738    
739     cpu->cpu_thread_running = TRUE;     gen->cpu_thread_running = TRUE;
740       cpu_exec_loop_set(gen);
741      
742   start_cpu:     start_cpu:  
743     cpu->idle_count = 0;     gen->idle_count = 0;
744    
745     for(;;) {     for(;;) {
746        if (unlikely(cpu->state != MIPS_CPU_RUNNING))        if (unlikely(gen->state != CPU_STATE_RUNNING))
747           break;           break;
748    
749  #if DEBUG_BLOCK_PERF_CNT  #if DEBUG_BLOCK_PERF_CNT
# Line 701  void *insn_block_execute(cpu_mips_t *cpu Line 751  void *insn_block_execute(cpu_mips_t *cpu
751  #endif  #endif
752        /* Handle virtual idle loop */        /* Handle virtual idle loop */
753        if (unlikely(cpu->pc == cpu->idle_pc)) {        if (unlikely(cpu->pc == cpu->idle_pc)) {
754           if (++cpu->idle_count == cpu->idle_max) {           if (++gen->idle_count == gen->idle_max) {
755              mips64_idle_loop(cpu);              cpu_idle_loop(gen);
756              cpu->idle_count = 0;              gen->idle_count = 0;
757           }           }
758        }        }
759    
# Line 718  void *insn_block_execute(cpu_mips_t *cpu Line 768  void *insn_block_execute(cpu_mips_t *cpu
768           }           }
769        }        }
770    
771        /* Get the physical page address corresponding to PC register */        pc_hash = mips64_jit_get_pc_hash(cpu->pc);
772        if (unlikely(cpu->translate(cpu,cpu->pc,&phys_page))) {        block = cpu->exec_blk_map[pc_hash];
          fprintf(stderr,"VM '%s': no physical page for CPU%u PC=0x%llx\n",  
                  cpu->vm->name,cpu->id,cpu->pc);  
          cpu_stop(cpu);  
          break;  
       }  
   
       block = cpu->exec_phys_map[phys_page];  
773    
774        /* No block found, compile the page */        /* No block found, compile the page */
775        if (unlikely(!block) || unlikely(!insn_block_match(cpu,block)))        if (unlikely(!block) || unlikely(!mips64_jit_tcb_match(cpu,block)))
776        {        {        
777           if (block != NULL) {           if (block != NULL) {
778              insn_block_free(cpu,block,TRUE);              mips64_jit_tcb_free(cpu,block,TRUE);
779              cpu->exec_phys_map[phys_page] = NULL;              cpu->exec_blk_map[pc_hash] = NULL;
780           }           }
781    
782           block = insn_page_compile(cpu,cpu->pc);           block = mips64_jit_tcb_compile(cpu,cpu->pc);
783           if (unlikely(!block)) {           if (unlikely(!block)) {
784              fprintf(stderr,              fprintf(stderr,
785                      "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",
786                      cpu->vm->name,cpu->id,cpu->pc);                      cpu->vm->name,gen->id,cpu->pc);
787              cpu_stop(cpu);              cpu_stop(gen);
788              break;              break;
789           }           }
790    
791           block->phys_page = phys_page;           cpu->exec_blk_map[pc_hash] = block;
          cpu->exec_phys_map[phys_page] = block;  
792        }        }
793    
794  #if DEBUG_BLOCK_TIMESTAMP  #if DEBUG_BLOCK_TIMESTAMP
795        block->tm_last_use = jit_jiffies++;        block->tm_last_use = jit_jiffies++;
796  #endif  #endif
797        block->acc_count++;        block->acc_count++;
798        insn_block_run(cpu,block);        mips64_jit_tcb_run(cpu,block);
799     }     }
800                
801     if (!cpu->pc) {     if (!cpu->pc) {
802        cpu_stop(cpu);        cpu_stop(gen);
803        cpu_log(cpu,"JIT","PC=0, halting CPU.\n");        cpu_log(gen,"JIT","PC=0, halting CPU.\n");
804     }     }
805    
806     /* Check regularly if the CPU has been restarted */     /* Check regularly if the CPU has been restarted */
807     while(cpu->cpu_thread_running) {     while(gen->cpu_thread_running) {
808        cpu->seq_state++;        gen->seq_state++;
809    
810        switch(cpu->state) {        switch(gen->state) {
811           case MIPS_CPU_RUNNING:           case CPU_STATE_RUNNING:
812              cpu->state = MIPS_CPU_RUNNING;              gen->state = CPU_STATE_RUNNING;
813              goto start_cpu;              goto start_cpu;
814    
815           case MIPS_CPU_HALTED:           case CPU_STATE_HALTED:
816              cpu->cpu_thread_running = FALSE;              gen->cpu_thread_running = FALSE;
817              pthread_join(timer_irq_thread,NULL);              pthread_join(timer_irq_thread,NULL);
818              break;              break;
819        }        }

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

  ViewVC Help
Powered by ViewVC 1.1.26