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

📄 ppc32_jit.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 3 页
字号:
            case JIT_OP_BRANCH_TARGET:            case JIT_OP_EOB:               ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);               for(j=0;j<8;j++)                  last_cr_update[j] = NULL;               break;            /* Branch jump: clear "store" operation status */            case JIT_OP_BRANCH_JUMP:               for(j=0;j<PPC32_GPR_NR;j++)                  ppc_map[j].last_store = NULL;               for(j=0;j<8;j++)                  last_cr_update[j] = NULL;               break;            /* Alteration of a specific host register */            case JIT_OP_ALTER_HOST_REG:               reg = op->param[0];               if (reg != JIT_OP_ALL_REGS) {                  if (host_map[reg] != JIT_OP_INV_REG)                     ppc32_clear_ppc_reg_map(ppc_map,host_map,host_map[reg]);               } else {                  ppc32_clear_ppc_reg_map(ppc_map,host_map,JIT_OP_ALL_REGS);               }               break;            /* Save reg mapping and last operation */            case JIT_OP_STORE_GPR:               reg = op->param[0];               map = &ppc_map[op->param[1]];               /* clear old mapping */               if (reg != map->host_reg) {                  ppc32_clear_host_reg_map(ppc_map,host_map,reg);                  ppc32_clear_ppc_reg_map(ppc_map,host_map,op->param[1]);               }                              /* cancel previous store op for this PPC register */               if (map->last_store) {                  map->last_store->param[0] = JIT_OP_INV_REG;                  map->last_store = NULL;               }               map->host_reg = reg;               map->last_store = op;               map->last_store_ia = cur_ia;               host_map[reg] = op->param[1];               break;            /* Load reg: check if can avoid it */            case JIT_OP_LOAD_GPR:               reg = op->param[0];               map = &ppc_map[op->param[1]];               if (reg == map->host_reg) {                  /* Cancel this load */                  op->param[0] = JIT_OP_INV_REG;               } else {                  /* clear old mapping */                  ppc32_clear_host_reg_map(ppc_map,host_map,reg);                  ppc32_clear_ppc_reg_map(ppc_map,host_map,op->param[1]);                  /* Save this reg mapping */                  map->host_reg = op->param[0];                  map->last_store = NULL;                  host_map[op->param[0]] = op->param[1];               }               break;            /* Trash flags */            case JIT_OP_TRASH_FLAGS:               for(j=0;j<8;j++)                  last_cr_update[j] = NULL;               break;            /* Flags required */            case JIT_OP_REQUIRE_FLAGS:               if (op->param[0] != JIT_OP_PPC_ALL_FLAGS) {                  last_cr_update[op->param[0]] = NULL;               } else {                  for(j=0;j<8;j++)                     last_cr_update[j] = NULL;               }               break;            /* Update flags */            case JIT_OP_UPDATE_FLAGS:               opx = last_cr_update[op->param[0]];               if (opx != NULL)                  opx->param[0] = JIT_OP_INV_REG;               last_cr_update[op->param[0]] = op;               break;         }      }   }}/* Generate the JIT code for the specified JIT op list */static void ppc32_op_gen_list(ppc32_jit_tcb_t *b,int ipos,jit_op_t *op_list,                              u_char *jit_start){   jit_op_t *op;   for(op=op_list;op;op=op->next) {      switch(op->opcode) {         case JIT_OP_INSN_OUTPUT:            ppc32_op_insn_output(b,op);            break;         case JIT_OP_LOAD_GPR:            ppc32_op_load_gpr(b,op);            break;         case JIT_OP_STORE_GPR:            ppc32_op_store_gpr(b,op);            break;         case JIT_OP_UPDATE_FLAGS:            ppc32_op_update_flags(b,op);            break;         case JIT_OP_BRANCH_TARGET:            b->jit_insn_ptr[ipos] = jit_start;            break;         case JIT_OP_MOVE_HOST_REG:            ppc32_op_move_host_reg(b,op);            break;         case JIT_OP_SET_HOST_REG_IMM32:            ppc32_op_set_host_reg_imm32(b,op);            break;      }   }}/* Opcode emit start */static inline void ppc32_op_emit_start(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b){   cpu_gen_t *c = cpu->gen;   jit_op_t *op;   if (c->jit_op_array[b->ppc_trans_pos] == NULL)      c->jit_op_current = &c->jit_op_array[b->ppc_trans_pos];   else {      for(op=c->jit_op_array[b->ppc_trans_pos];op;op=op->next)         c->jit_op_current = &op->next;   }}/* Generate the JIT code for the current page, given an op list */static int ppc32_op_gen_page(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b){      struct ppc32_insn_tag *tag;   cpu_gen_t *gcpu = cpu->gen;   jit_op_t *iop;   m_uint32_t cur_ia;   u_char *jit_ptr;   int i;   /* Generate JIT opcodes */   for(b->ppc_trans_pos=0;       b->ppc_trans_pos<PPC32_INSN_PER_PAGE;       b->ppc_trans_pos++)    {      ppc32_op_emit_start(cpu,b);      cur_ia = b->start_ia + (b->ppc_trans_pos << 2);      if (ppc32_jit_tcb_get_target_bit(b,cur_ia))         ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);#if DEBUG_INSN_PERF_CNT      ppc32_inc_perf_counter(cpu);#endif#if BREAKPOINT_ENABLE      if (cpu->breakpoints_enabled)         insn_emit_breakpoint(cpu,b);#endif      if (unlikely(!(tag = ppc32_jit_fetch_and_emit(cpu,b)))) {         fprintf(stderr,"ppc32_op_gen_page: unable to fetch instruction.\n");         return(-1);      }   }   /*     * Mark the first instruction as a potential target, as well as the     * current IA value.    */   ppc32_op_emit_branch_target(cpu,b,b->start_ia);   ppc32_op_emit_branch_target(cpu,b,cpu->ia);   /* Optimize condition register and general registers */   ppc32_op_optimize(gcpu,b);   /* Generate JIT code for each instruction in page */   for(i=0;i<PPC32_INSN_PER_PAGE;i++)    {      jit_ptr = b->jit_ptr;      /* Generate output code */      ppc32_op_gen_list(b,i,gcpu->jit_op_array[i],jit_ptr);      /* Adjust the JIT buffer if its size is not sufficient */      ppc32_jit_tcb_adjust_buffer(cpu,b);   }   /* Apply patches and free opcodes */   for(i=0;i<PPC32_INSN_PER_PAGE;i++) {      for(iop=gcpu->jit_op_array[i];iop;iop=iop->next)         if (iop->opcode == JIT_OP_INSN_OUTPUT)            ppc32_jit_tcb_apply_patches(cpu,b,iop);      jit_op_free_list(gcpu,gcpu->jit_op_array[i]);      gcpu->jit_op_array[i] = NULL;   }   /* Add end of page (returns to caller) */   ppc32_set_page_jump(cpu,b);   /* Free patch tables */   ppc32_jit_tcb_free_patches(b);   return(0);}/* ======================================================================== *//* Compile a PowerPC instruction page */static inline ppc32_jit_tcb_t *ppc32_jit_tcb_compile(cpu_ppc_t *cpu,m_uint32_t vaddr){     ppc32_jit_tcb_t *block;   m_uint32_t page_addr;   page_addr = vaddr & ~PPC32_MIN_PAGE_IMASK;   if (unlikely(!(block = ppc32_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 PPC code ptr to native code ptr */   if (!(block->jit_insn_ptr = calloc(PPC32_INSN_PER_PAGE,sizeof(u_char *)))) {      fprintf(stderr,"insn_page_compile: unable to create JIT mappings.\n");      goto error;   }   /* Compile the page */   if (ppc32_op_gen_page(cpu,block) == -1) {      fprintf(stderr,"insn_page_compile: unable to compile page.\n");      goto error;   }      /* 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;      /* Add the block to the physical mapping hash table */   block->phys_next = cpu->exec_phys_map[block->phys_hash];   block->phys_pprev = &cpu->exec_phys_map[block->phys_hash];   if (cpu->exec_phys_map[block->phys_hash] != NULL)      cpu->exec_phys_map[block->phys_hash]->phys_pprev = &block->phys_next;   cpu->exec_phys_map[block->phys_hash] = block;   cpu->compiled_pages++;   return block; error:   ppc32_jit_tcb_free(cpu,block,FALSE);   return NULL;}/* Recompile a page */int ppc32_jit_tcb_recompile(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block){#if 0   printf("PPC32-JIT: recompiling page 0x%8.8x\n",block->start_ia);#endif   /* Free old code chunks */   ppc32_jit_tcb_free_code_chunks(cpu,block);   /* Reset code ptr array */   memset(block->jit_insn_ptr,0,PPC32_INSN_PER_PAGE * sizeof(u_char *));   /* Allocate the first JIT buffer */   if (!(block->jit_buffer = exec_page_alloc(cpu)))      return(-1);   /* Recompile the page */   if (ppc32_op_gen_page(cpu,block) == -1) {      fprintf(stderr,"insn_page_compile: unable to recompile page.\n");      return(-1);   }   block->target_undef_cnt = 0;   return(0);}/* Run a compiled PowerPC instruction block */static forced_inlinevoid ppc32_jit_tcb_run(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block){   if (unlikely(cpu->ia & 0x03)) {      fprintf(stderr,"ppc32_jit_tcb_run: Invalid IA 0x%8.8x.\n",cpu->ia);      ppc32_dump_regs(cpu->gen);      ppc32_dump_mmu(cpu->gen);      cpu_stop(cpu->gen);      return;   }   /* Execute JIT compiled code */   ppc32_jit_tcb_exec(cpu,block);}/* Execute compiled PowerPC code */void *ppc32_jit_run_cpu(cpu_gen_t *gen){       cpu_ppc_t *cpu = CPU_PPC32(gen);   pthread_t timer_irq_thread;   ppc32_jit_tcb_t *block;   m_uint32_t ia_hash;   int timer_irq_check = 0;   ppc32_jit_init_hreg_mapping(cpu);   if (pthread_create(&timer_irq_thread,NULL,(void *)ppc32_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->ia == 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 &&             (cpu->msr & PPC32_MSR_EE))         {            cpu->timer_irq_armed = 0;            cpu->timer_irq_pending--;            vm_set_irq(cpu->vm,0);         }      }      /* Check IRQs */      if (unlikely(cpu->irq_check))         ppc32_trigger_irq(cpu);      /* Get the JIT block corresponding to IA register */      ia_hash = ppc32_jit_get_ia_hash(cpu->ia);      block = cpu->exec_blk_map[ia_hash];            /* No block found, compile the page */      if (unlikely(!block) || unlikely(!ppc32_jit_tcb_match(cpu,block)))       {         if (block != NULL) {            ppc32_jit_tcb_free(cpu,block,TRUE);            cpu->exec_blk_map[ia_hash] = NULL;         }         block = ppc32_jit_tcb_compile(cpu,cpu->ia);         if (unlikely(!block)) {            fprintf(stderr,                    "VM '%s': unable to compile block for CPU%u IA=0x%8.8x\n",                    cpu->vm->name,gen->id,cpu->ia);            cpu_stop(gen);            break;         }         cpu->exec_blk_map[ia_hash] = block;      }#if DEBUG_BLOCK_TIMESTAMP      block->tm_last_use = jit_jiffies++;#endif      block->acc_count++;      ppc32_jit_tcb_run(cpu,block);   }         if (!cpu->ia) {      cpu_stop(gen);      cpu_log(gen,"JIT","IA=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);            break;      }            /* CPU is paused */      usleep(200000);   }   return NULL;}

⌨️ 快捷键说明

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