⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mips64_jit.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 2 页
字号:
              block->start_pc,vaddr,block->mips_trans_pos);      return(-1);   }   if (!ipt || (ipt->cur_patch >= MIPS64_INSN_PATCH_TABLE_SIZE))   {      /* full table or no table, create a new one */      ipt = malloc(sizeof(*ipt));      if (!ipt) {         fprintf(stderr,"Block 0x%8.8llx: unable to create patch table.\n",                 block->start_pc);         return(-1);      }      memset(ipt,0,sizeof(*ipt));      ipt->next = block->patch_table;      block->patch_table = ipt;   }#if DEBUG_BLOCK_PATCH   printf("Block 0x%8.8llx: recording patch [JIT:%p->mips:0x%8.8llx], "          "MTP=%d\n",block->start_pc,jit_ptr,vaddr,block->mips_trans_pos);#endif   patch = &ipt->patches[ipt->cur_patch];   patch->jit_insn = jit_ptr;   patch->mips_pc = vaddr;   ipt->cur_patch++;      return(0);}/* Apply all patches */static int mips64_jit_tcb_apply_patches(cpu_mips_t *cpu,                                        mips64_jit_tcb_t *block){   struct mips64_jit_patch_table *ipt;   struct mips64_insn_patch *patch;   u_char *jit_dst;   int i;   for(ipt=block->patch_table;ipt;ipt=ipt->next)      for(i=0;i<ipt->cur_patch;i++)       {         patch = &ipt->patches[i];         jit_dst = mips64_jit_tcb_get_host_ptr(block,patch->mips_pc);         if (jit_dst) {#if DEBUG_BLOCK_PATCH            printf("Block 0x%8.8llx: applying patch "                   "[JIT:%p->mips:0x%8.8llx=JIT:%p]\n",                   block->start_pc,patch->jit_insn,patch->mips_pc,jit_dst);#endif            mips64_jit_tcb_set_patch(patch->jit_insn,jit_dst);         }      }   return(0);}/* Free the patch table */static void mips64_jit_tcb_free_patches(mips64_jit_tcb_t *block){   struct mips64_jit_patch_table *p,*next;   for(p=block->patch_table;p;p=next) {      next = p->next;      free(p);   }   block->patch_table = NULL;}/* Adjust the JIT buffer if its size is not sufficient */static int mips64_jit_tcb_adjust_buffer(cpu_mips_t *cpu,                                        mips64_jit_tcb_t *block){   insn_exec_page_t *new_buffer;   if ((block->jit_ptr - block->jit_buffer->ptr) <= (MIPS_JIT_BUFSIZE - 512))      return(0);#if DEBUG_BLOCK_CHUNK     printf("Block 0x%llx: adjusting JIT buffer...\n",block->start_pc);#endif   if (block->jit_chunk_pos >= MIPS_JIT_MAX_CHUNKS) {      fprintf(stderr,"Block 0x%llx: too many JIT chunks.\n",block->start_pc);      return(-1);   }   if (!(new_buffer = exec_page_alloc(cpu)))      return(-1);   /* record the new exec page */   block->jit_chunks[block->jit_chunk_pos++] = block->jit_buffer;   block->jit_buffer = new_buffer;   /* jump to the new exec page (link) */   mips64_jit_tcb_set_jump(block->jit_ptr,new_buffer->ptr);   block->jit_ptr = new_buffer->ptr;   return(0);}/* Allocate an instruction block */static inline mips64_jit_tcb_t *mips64_jit_tcb_alloc(cpu_mips_t *cpu){   mips64_jit_tcb_t *p;   if (cpu->tcb_free_list) {      p = cpu->tcb_free_list;      cpu->tcb_free_list = p->next;   } else {      if (!(p = malloc(sizeof(*p))))         return NULL;   }   memset(p,0,sizeof(*p));   return p;}/* Free an instruction block */void mips64_jit_tcb_free(cpu_mips_t *cpu,mips64_jit_tcb_t *block,                         int list_removal){   int i;   if (block) {      if (list_removal) {         /* Remove the block from the linked list */         if (block->next)            block->next->prev = block->prev;         else            cpu->tcb_last = block->prev;         if (block->prev)            block->prev->next = block->next;         else            cpu->tcb_list = block->next;      }      /* Free the patch tables */      mips64_jit_tcb_free_patches(block);      /* Free code pages */      for(i=0;i<MIPS_JIT_MAX_CHUNKS;i++)         exec_page_free(cpu,block->jit_chunks[i]);      /* Free the current JIT buffer */      exec_page_free(cpu,block->jit_buffer);      /* Free the MIPS-to-native code mapping */      free(block->jit_insn_ptr);      /* Make the block return to the free list */      block->next = cpu->tcb_free_list;      cpu->tcb_free_list = block;   }}/* Create an instruction block */static mips64_jit_tcb_t *mips64_jit_tcb_create(cpu_mips_t *cpu,                                               m_uint64_t vaddr){   mips64_jit_tcb_t *block = NULL;   if (!(block = mips64_jit_tcb_alloc(cpu)))      goto err_block_alloc;   block->start_pc = vaddr;   /* Allocate the first JIT buffer */   if (!(block->jit_buffer = exec_page_alloc(cpu)))      goto err_jit_alloc;   block->jit_ptr = block->jit_buffer->ptr;   block->mips_code = cpu->mem_op_lookup(cpu,block->start_pc);   if (!block->mips_code) {      fprintf(stderr,"%% No memory map for code execution at 0x%llx\n",              block->start_pc);      goto err_lookup;   }#if DEBUG_BLOCK_TIMESTAMP   block->tm_first_use = block->tm_last_use = jit_jiffies;#endif   return block; err_lookup: err_jit_alloc:   mips64_jit_tcb_free(cpu,block,FALSE); err_block_alloc:   fprintf(stderr,"%% Unable to create instruction block for vaddr=0x%llx\n",            vaddr);   return NULL;}/* Compile a MIPS instruction page */static inline mips64_jit_tcb_t *mips64_jit_tcb_compile(cpu_mips_t *cpu,m_uint64_t vaddr){     mips64_jit_tcb_t *block;   struct mips64_insn_tag *tag;   m_uint64_t page_addr;   size_t len;   page_addr = vaddr & ~(m_uint64_t)MIPS_MIN_PAGE_IMASK;   if (unlikely(!(block = mips64_jit_tcb_create(cpu,page_addr)))) {      fprintf(stderr,"insn_page_compile: unable to create JIT block.\n");      return NULL;   }   /* Allocate the array used to convert MIPS code ptr to native code ptr */   len = MIPS_MIN_PAGE_SIZE / sizeof(mips_insn_t);   if (!(block->jit_insn_ptr = calloc(len,sizeof(u_char *)))) {      fprintf(stderr,"insn_page_compile: unable to create JIT mappings.\n");      goto error;   }   /* Emit native code for each instruction */   block->mips_trans_pos = 0;   while(block->mips_trans_pos < MIPS_INSN_PER_PAGE)   {      if (unlikely(!(tag = mips64_jit_fetch_and_emit(cpu,block,0)))) {         fprintf(stderr,"insn_page_compile: unable to fetch instruction.\n");         goto error;      }#if DEBUG_BLOCK_COMPILE      printf("Page 0x%8.8llx: emitted tag 0x%8.8x/0x%8.8x\n",             block->start_pc,tag->mask,tag->value);#endif      mips64_jit_tcb_adjust_buffer(cpu,block);   }   mips64_jit_tcb_add_end(block);   mips64_jit_tcb_apply_patches(cpu,block);   mips64_jit_tcb_free_patches(block);   /* Add the block to the linked list */   block->next = cpu->tcb_list;   block->prev = NULL;   if (cpu->tcb_list)      cpu->tcb_list->prev = block;   else      cpu->tcb_last = block;   cpu->tcb_list = block;      cpu->compiled_pages++;   return block; error:   mips64_jit_tcb_free(cpu,block,FALSE);   return NULL;}/* Run a compiled MIPS instruction block */static forced_inline void mips64_jit_tcb_run(cpu_mips_t *cpu,mips64_jit_tcb_t *block){#if DEBUG_SYM_TREE   struct symbol *sym = NULL;   int mark = FALSE;#endif   if (unlikely(cpu->pc & 0x03)) {      fprintf(stderr,"mips64_jit_tcb_run: Invalid PC 0x%llx.\n",cpu->pc);      mips64_dump_regs(cpu->gen);      mips64_tlb_dump(cpu->gen);      cpu_stop(cpu->gen);      return;   }#if DEBUG_SYM_TREE   if (cpu->sym_trace && cpu->sym_tree)   {      if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {         cpu_log(cpu,"mips64_jit_tcb_run(start)",                 "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "                 "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",                 sym->name, cpu->pc, cpu->gpr[MIPS_GPR_RA],                 cpu->gpr[MIPS_GPR_A0], cpu->gpr[MIPS_GPR_A1],                 cpu->gpr[MIPS_GPR_A2], cpu->gpr[MIPS_GPR_A3]);         mark = TRUE;      }   }#endif   /* Execute JIT compiled code */   mips64_jit_tcb_exec(cpu,block);#if DEBUG_SYM_TREE   if (mark) {      cpu_log(cpu,"mips64_jit_tcb_run(end)","%s, v0 = 0x%llx\n",              sym->name,cpu->gpr[MIPS_GPR_V0]);   }#endif}/* Execute compiled MIPS code */void *mips64_jit_run_cpu(cpu_gen_t *gen){       cpu_mips_t *cpu = CPU_MIPS64(gen);   pthread_t timer_irq_thread;   mips64_jit_tcb_t *block;   int timer_irq_check = 0;   m_uint32_t pc_hash;   if (pthread_create(&timer_irq_thread,NULL,                      (void *)mips64_timer_irq_run,cpu))    {      fprintf(stderr,              "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",              cpu->vm->name,gen->id);      cpu_stop(cpu->gen);      return NULL;   }   gen->cpu_thread_running = TRUE;   cpu_exec_loop_set(gen);    start_cpu:      gen->idle_count = 0;   for(;;) {      if (unlikely(gen->state != CPU_STATE_RUNNING))         break;#if DEBUG_BLOCK_PERF_CNT      cpu->perf_counter++;#endif      /* Handle virtual idle loop */      if (unlikely(cpu->pc == cpu->idle_pc)) {         if (++gen->idle_count == gen->idle_max) {            cpu_idle_loop(gen);            gen->idle_count = 0;         }      }      /* Handle the virtual CPU clock */      if (++timer_irq_check == cpu->timer_irq_check_itv) {         timer_irq_check = 0;         if (cpu->timer_irq_pending && !cpu->irq_disable) {            mips64_trigger_timer_irq(cpu);            mips64_trigger_irq(cpu);            cpu->timer_irq_pending--;         }      }      pc_hash = mips64_jit_get_pc_hash(cpu->pc);      block = cpu->exec_blk_map[pc_hash];      /* No block found, compile the page */      if (unlikely(!block) || unlikely(!mips64_jit_tcb_match(cpu,block)))       {                 if (block != NULL) {            mips64_jit_tcb_free(cpu,block,TRUE);            cpu->exec_blk_map[pc_hash] = NULL;         }         block = mips64_jit_tcb_compile(cpu,cpu->pc);         if (unlikely(!block)) {            fprintf(stderr,                    "VM '%s': unable to compile block for CPU%u PC=0x%llx\n",                    cpu->vm->name,gen->id,cpu->pc);            cpu_stop(gen);            break;         }         cpu->exec_blk_map[pc_hash] = block;      }#if DEBUG_BLOCK_TIMESTAMP      block->tm_last_use = jit_jiffies++;#endif      block->acc_count++;      mips64_jit_tcb_run(cpu,block);   }         if (!cpu->pc) {      cpu_stop(gen);      cpu_log(gen,"JIT","PC=0, halting CPU.\n");   }   /* Check regularly if the CPU has been restarted */   while(gen->cpu_thread_running) {      gen->seq_state++;      switch(gen->state) {         case CPU_STATE_RUNNING:            gen->state = CPU_STATE_RUNNING;            goto start_cpu;         case CPU_STATE_HALTED:            gen->cpu_thread_running = FALSE;            pthread_join(timer_irq_thread,NULL);            return NULL;      }            /* CPU is paused */      usleep(200000);   }   return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -