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

📄 ppc32_jit.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * PPC32 JIT compiler. */#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <signal.h>#include <fcntl.h>#include <assert.h>#include "cpu.h"#include "device.h"#include "ppc32.h"#include "ppc32_exec.h"#include "ppc32_jit.h"#include "insn_lookup.h"#include "memory.h"#include "ptask.h"#include PPC32_ARCH_INC_FILE/* Instruction Lookup Table */static insn_lookup_t *ilt = NULL;static void *ppc32_jit_get_insn(int index){   return(&ppc32_insn_tags[index]);}static int ppc32_jit_chk_lo(struct ppc32_insn_tag *tag,int value){   return((value & tag->mask) == (tag->value & 0xFFFF));}static int ppc32_jit_chk_hi(struct ppc32_insn_tag *tag,int value){   return((value & (tag->mask >> 16)) == (tag->value >> 16));}/* Initialize instruction lookup table */void ppc32_jit_create_ilt(void){   int i,count;   for(i=0,count=0;ppc32_insn_tags[i].emit;i++)      count++;   ilt = ilt_create("ppc32j",count,                    (ilt_get_insn_cbk_t)ppc32_jit_get_insn,                    (ilt_check_cbk_t)ppc32_jit_chk_lo,                    (ilt_check_cbk_t)ppc32_jit_chk_hi);}/* Initialize the JIT structure */int ppc32_jit_init(cpu_ppc_t *cpu){   insn_exec_page_t *cp;   u_char *cp_addr;   u_int area_size;   size_t len;   int i;   /* JIT mapping for executable pages */   len = PPC_JIT_IA_HASH_SIZE * sizeof(void *);   cpu->exec_blk_map = m_memalign(4096,len);   memset(cpu->exec_blk_map,0,len);   /* Physical mapping for executable pages */   len = PPC_JIT_PHYS_HASH_SIZE * sizeof(void *);   cpu->exec_phys_map = m_memalign(4096,len);   memset(cpu->exec_phys_map,0,len);   /* Get area size */   if (!(area_size = cpu->vm->exec_area_size))      area_size = PPC_EXEC_AREA_SIZE;   /* Create executable page area */   cpu->exec_page_area_size = area_size * 1048576;   cpu->exec_page_area = mmap(NULL,cpu->exec_page_area_size,                              PROT_EXEC|PROT_READ|PROT_WRITE,                              MAP_SHARED|MAP_ANONYMOUS,-1,(off_t)0);   if (!cpu->exec_page_area) {      fprintf(stderr,              "ppc32_jit_init: unable to create exec area (size %lu)\n",              (u_long)cpu->exec_page_area_size);      return(-1);   }   /* Carve the executable page area */   cpu->exec_page_count = cpu->exec_page_area_size / PPC_JIT_BUFSIZE;   cpu->exec_page_array = calloc(cpu->exec_page_count,                                 sizeof(insn_exec_page_t));      if (!cpu->exec_page_array) {      fprintf(stderr,"ppc32_jit_init: unable to create exec page array\n");      return(-1);   }   for(i=0,cp_addr=cpu->exec_page_area;i<cpu->exec_page_count;i++) {      cp = &cpu->exec_page_array[i];      cp->ptr = cp_addr;      cp_addr += PPC_JIT_BUFSIZE;      cp->next = cpu->exec_page_free_list;      cpu->exec_page_free_list = cp;   }   printf("CPU%u: carved JIT exec zone of %lu Mb into %lu pages of %u Kb.\n",          cpu->gen->id,          (u_long)(cpu->exec_page_area_size / 1048576),          (u_long)cpu->exec_page_count,PPC_JIT_BUFSIZE / 1024);   return(0);}/* Flush the JIT */u_int ppc32_jit_flush(cpu_ppc_t *cpu,u_int threshold){   ppc32_jit_tcb_t *p,*next;   m_uint32_t ia_hash;   u_int count = 0;   if (!threshold)      threshold = (u_int)(-1);  /* UINT_MAX not defined everywhere */   for(p=cpu->tcb_list;p;p=next) {      next = p->next;      if (p->acc_count <= threshold) {         ia_hash = ppc32_jit_get_ia_hash(p->start_ia);         ppc32_jit_tcb_free(cpu,p,TRUE);         if (cpu->exec_blk_map[ia_hash] == p)            cpu->exec_blk_map[ia_hash] = NULL;         count++;      }   }   cpu->compiled_pages -= count;   return(count);}/* Shutdown the JIT */void ppc32_jit_shutdown(cpu_ppc_t *cpu){      ppc32_jit_tcb_t *p,*next;   /* Flush the JIT */   ppc32_jit_flush(cpu,0);   /* Free the instruction blocks */   for(p=cpu->tcb_free_list;p;p=next) {      next = p->next;      free(p);   }   /* Unmap the executable page area */   if (cpu->exec_page_area)      munmap(cpu->exec_page_area,cpu->exec_page_area_size);   /* Free the exec page array */   free(cpu->exec_page_array);   /* Free JIT block mapping */   free(cpu->exec_blk_map);      /* Free physical mapping for executable pages */   free(cpu->exec_phys_map);}/* Allocate an exec page */static inline insn_exec_page_t *exec_page_alloc(cpu_ppc_t *cpu){   insn_exec_page_t *p;   u_int count;   /* If the free list is empty, flush JIT */   if (unlikely(!cpu->exec_page_free_list))    {      if (cpu->jit_flush_method) {         cpu_log(cpu->gen,                 "JIT","flushing data structures (compiled pages=%u)\n",                 cpu->compiled_pages);         ppc32_jit_flush(cpu,0);      } else {         count = ppc32_jit_flush(cpu,100);         cpu_log(cpu->gen,"JIT","partial JIT flush (count=%u)\n",count);         if (!cpu->exec_page_free_list)            ppc32_jit_flush(cpu,0);      }            /* Use both methods alternatively */      cpu->jit_flush_method = 1 - cpu->jit_flush_method;   }   if (unlikely(!(p = cpu->exec_page_free_list)))      return NULL;      cpu->exec_page_free_list = p->next;   cpu->exec_page_alloc++;   return p;}/* Free an exec page and returns it to the pool */static inline void exec_page_free(cpu_ppc_t *cpu,insn_exec_page_t *p){   if (p) {      p->next = cpu->exec_page_free_list;      cpu->exec_page_free_list = p;      cpu->exec_page_alloc--;   }}/* Find the JIT code emitter for the specified PowerPC instruction */static struct ppc32_insn_tag *insn_tag_find(ppc_insn_t ins){   struct ppc32_insn_tag *tag = NULL;   int index;   index = ilt_lookup(ilt,ins);      tag = ppc32_jit_get_insn(index);   return tag;}/* Fetch a PowerPC instruction */static forced_inline ppc_insn_t insn_fetch(ppc32_jit_tcb_t *b){   return(vmtoh32(b->ppc_code[b->ppc_trans_pos]));}#define DEBUG_HREG  0/* Show register allocation status */static void ppc32_jit_show_hreg_status(cpu_ppc_t *cpu){       struct hreg_map *map;   printf("PPC32-JIT: reg status for insn '%s'\n",cpu->jit_hreg_seq_name);   for(map=cpu->hreg_map_list;map;map=map->next) {      switch(map->flags) {         case 0:            printf("   hreg %d is free, mapped to vreg %d\n",                   map->hreg,map->vreg);            break;         case HREG_FLAG_ALLOC_LOCKED:            printf("   hreg %d is locked, mapped to vreg %d\n",                   map->hreg,map->vreg);            break;         case HREG_FLAG_ALLOC_FORCED:            printf("   hreg %d is in forced alloc\n",map->hreg);            break;      }   }}/* Extract an host reg mapping from the register list */static void ppc32_jit_extract_hreg(cpu_ppc_t *cpu,struct hreg_map *map){   if (map->prev != NULL)      map->prev->next = map->next;   else      cpu->hreg_map_list = map->next;   if (map->next != NULL)      map->next->prev = map->prev;   else      cpu->hreg_lru = map->prev;}/* Insert a reg map as head of list (as MRU element) */void ppc32_jit_insert_hreg_mru(cpu_ppc_t *cpu,struct hreg_map *map){   map->next = cpu->hreg_map_list;   map->prev = NULL;   if (map->next == NULL) {      cpu->hreg_lru = map;   } else {      map->next->prev = map;   }   cpu->hreg_map_list = map;}/* Start register allocation sequence */void ppc32_jit_start_hreg_seq(cpu_ppc_t *cpu,char *insn){   struct hreg_map *map;#if DEBUG_HREG   printf("Starting hreg_seq insn='%s'\n",insn);#endif   /* Reset the allocation state of all host registers */   for(map=cpu->hreg_map_list;map;map=map->next)      map->flags = 0;   /* Save the instruction name for debugging/error analysis */   cpu->jit_hreg_seq_name = insn;}/* Close register allocation sequence */void ppc32_jit_close_hreg_seq(cpu_ppc_t *cpu){#if DEBUG_HREG   ppc32_show_hreg_status(cpu);#endif}/* Find a free host register to use */static struct hreg_map *ppc32_jit_get_free_hreg(cpu_ppc_t *cpu){   struct hreg_map *map,*oldest_free = NULL;   for(map=cpu->hreg_lru;map;map=map->prev) {      if ((map->vreg == -1) && (map->flags == 0))         return map;      if ((map->flags == 0) && !oldest_free)         oldest_free = map;   }   if (!oldest_free) {      fprintf(stderr,              "ppc32_get_free_hreg: unable to find free reg for insn %s\n",              cpu->jit_hreg_seq_name);   }   return oldest_free;}/* Allocate an host register */int ppc32_jit_alloc_hreg(cpu_ppc_t *cpu,int ppc_reg){   struct hreg_map *map;   int hreg;   /*     * If PPC reg is invalid, the caller requested for a temporary register.    */   if (ppc_reg == -1) {      if ((map = ppc32_jit_get_free_hreg(cpu)) == NULL)         return(-1);      /* Allocate the register and invalidate its PPC mapping if present */      map->flags = HREG_FLAG_ALLOC_LOCKED;      if (map->vreg != -1) {         cpu->ppc_reg_map[map->vreg] = -1;         map->vreg = -1;      }      return(map->hreg);   }   hreg = cpu->ppc_reg_map[ppc_reg];   /*     * If the PPC register is already mapped to an host register, re-use this    * mapping and put this as MRU mapping.    */   if (hreg != -1) {      map = &cpu->hreg_map[hreg];   } else {      /*        * This PPC register has no mapping to host register. Find a free       * register.       */      if ((map = ppc32_jit_get_free_hreg(cpu)) == NULL)         return(-1);      /* Remove the old PPC mapping if present */      if (map->vreg != -1)         cpu->ppc_reg_map[map->vreg] = -1;            /* Establish the new mapping */      cpu->ppc_reg_map[ppc_reg] = map->hreg;      map->vreg = ppc_reg;   }   /* Prevent this register from further allocation in this instruction */   map->flags = HREG_FLAG_ALLOC_LOCKED;   ppc32_jit_extract_hreg(cpu,map);   ppc32_jit_insert_hreg_mru(cpu,map);   return(map->hreg);}/* Force allocation of an host register */int ppc32_jit_alloc_hreg_forced(cpu_ppc_t *cpu,int hreg){   int ppc_reg;   ppc_reg = cpu->hreg_map[hreg].vreg;   /* Check that this register is not already allocated */   if (cpu->hreg_map[hreg].flags != 0) {      fprintf(stderr,"ppc32_alloc_hreg_forced: trying to force allocation "              "of hreg %d (insn %s)\n",              hreg,cpu->jit_hreg_seq_name);      return(-1);   }   cpu->hreg_map[hreg].flags = HREG_FLAG_ALLOC_FORCED;   cpu->hreg_map[hreg].vreg  = -1;   if (ppc_reg != -1)      cpu->ppc_reg_map[ppc_reg] = -1;   return(0);}/* Emit a breakpoint if necessary */#if BREAKPOINT_ENABLEstatic void insn_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b){   m_uint32_t ia;   int i;   ia = b->start_ia+((b->ppc_trans_pos-1)<<2);   for(i=0;i<PPC32_MAX_BREAKPOINTS;i++)      if (ia == cpu->breakpoints[i]) {         ppc32_emit_breakpoint(cpu,b);         break;      }}#endif /* BREAKPOINT_ENABLE *//* Fetch a PowerPC instruction and emit corresponding translated code */struct ppc32_insn_tag *ppc32_jit_fetch_and_emit(cpu_ppc_t *cpu,

⌨️ 快捷键说明

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