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

📄 mips64_jit.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) * * MIPS64 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 "sbox.h"#include "cpu.h"#include "device.h"#include "mips64.h"#include "mips64_cp0.h"#include "mips64_exec.h"#include "mips64_jit.h"#include "insn_lookup.h"#include "memory.h"#include "ptask.h"#include MIPS64_ARCH_INC_FILE#if DEBUG_BLOCK_TIMESTAMPstatic volatile m_uint64_t jit_jiffies = 0;#endif/* MIPS jump instructions for block scan */struct mips64_insn_jump mips64_insn_jumps[] = {   { "b"       , 0xffff0000, 0x10000000, 16, 1 },   { "bal"     , 0xffff0000, 0x04110000, 16, 1 },   { "beq"     , 0xfc000000, 0x10000000, 16, 1 },   { "beql"    , 0xfc000000, 0x50000000, 16, 1 },   { "bgez"    , 0xfc1f0000, 0x04010000, 16, 1 },   { "bgezl"   , 0xfc1f0000, 0x04030000, 16, 1 },   { "bgezal"  , 0xfc1f0000, 0x04110000, 16, 1 },   { "bgezall" , 0xfc1f0000, 0x04130000, 16, 1 },   { "bgtz"    , 0xfc1f0000, 0x1c000000, 16, 1 },   { "bgtzl"   , 0xfc1f0000, 0x5c000000, 16, 1 },   { "blez"    , 0xfc1f0000, 0x18000000, 16, 1 },   { "blezl"   , 0xfc1f0000, 0x58000000, 16, 1 },   { "bltz"    , 0xfc1f0000, 0x04000000, 16, 1 },   { "bltzl"   , 0xfc1f0000, 0x04020000, 16, 1 },   { "bltzal"  , 0xfc1f0000, 0x04100000, 16, 1 },   { "bltzall" , 0xfc1f0000, 0x04120000, 16, 1 },   { "bne"     , 0xfc000000, 0x14000000, 16, 1 },   { "bnel"    , 0xfc000000, 0x54000000, 16, 1 },   { "j"       , 0xfc000000, 0x08000000, 26, 0 },   { NULL      , 0x00000000, 0x00000000,  0, 0 },};/* Instruction Lookup Table */static insn_lookup_t *ilt = NULL;static void *mips64_jit_get_insn(int index){   return(&mips64_insn_tags[index]);}static int mips64_jit_chk_lo(struct mips64_insn_tag *tag,int value){   return((value & tag->mask) == (tag->value & 0xFFFF));}static int mips64_jit_chk_hi(struct mips64_insn_tag *tag,int value){   return((value & (tag->mask >> 16)) == (tag->value >> 16));}/* Initialize instruction lookup table */void mips64_jit_create_ilt(void){   int i,count;   for(i=0,count=0;mips64_insn_tags[i].emit;i++)      count++;   ilt = ilt_create("mips64j",count,                    (ilt_get_insn_cbk_t)mips64_jit_get_insn,                    (ilt_check_cbk_t)mips64_jit_chk_lo,                    (ilt_check_cbk_t)mips64_jit_chk_hi);}/* Initialize the JIT structure */int mips64_jit_init(cpu_mips_t *cpu){   insn_exec_page_t *cp;   u_char *cp_addr;   u_int area_size;   size_t len;   int i;   /* Physical mapping for executable pages */   len = MIPS_JIT_PC_HASH_SIZE * sizeof(void *);   cpu->exec_blk_map = m_memalign(4096,len);   memset(cpu->exec_blk_map,0,len);   /* Get area size */   if (!(area_size = cpu->vm->exec_area_size))      area_size = MIPS_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,              "mips64_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 / MIPS_JIT_BUFSIZE;   cpu->exec_page_array = calloc(cpu->exec_page_count,                                 sizeof(insn_exec_page_t));      if (!cpu->exec_page_array) {      fprintf(stderr,"mips64_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 += MIPS_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,MIPS_JIT_BUFSIZE / 1024);   return(0);}/* Flush the JIT */u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold){   mips64_jit_tcb_t *p,*next;   m_uint32_t pc_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) {         pc_hash = mips64_jit_get_pc_hash(p->start_pc);         cpu->exec_blk_map[pc_hash] = NULL;         mips64_jit_tcb_free(cpu,p,TRUE);         count++;      }   }   cpu->compiled_pages -= count;   return(count);}/* Shutdown the JIT */void mips64_jit_shutdown(cpu_mips_t *cpu){      mips64_jit_tcb_t *p,*next;   /* Flush the JIT */   mips64_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 physical mapping for executable pages */   free(cpu->exec_blk_map);   }/* Allocate an exec page */static inline insn_exec_page_t *exec_page_alloc(cpu_mips_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);         mips64_jit_flush(cpu,0);      } else {         count = mips64_jit_flush(cpu,100);         cpu_log(cpu->gen,"JIT","partial JIT flush (count=%u)\n",count);         if (!cpu->exec_page_free_list)            mips64_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_mips_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 MIPS instruction */static struct mips64_insn_tag *insn_tag_find(mips_insn_t ins){   struct mips64_insn_tag *tag = NULL;   int index;   index = ilt_lookup(ilt,ins);   tag = mips64_jit_get_insn(index);   return tag;}/* Check if the specified MIPS instruction is a jump */static struct mips64_insn_jump *insn_jump_find(mips_insn_t ins){   struct mips64_insn_jump *jump = NULL;   int i;   for(i=0;mips64_insn_jumps[i].name;i++)      if ((ins & mips64_insn_jumps[i].mask) == mips64_insn_jumps[i].value) {         jump = &mips64_insn_jumps[i];         break;      }   return(jump);}/* Fetch a MIPS instruction */static forced_inline mips_insn_t insn_fetch(mips64_jit_tcb_t *b){   return(vmtoh32(b->mips_code[b->mips_trans_pos]));}/* Emit a breakpoint if necessary */#if BREAKPOINT_ENABLEstatic void insn_emit_breakpoint(cpu_mips_t *cpu,mips64_jit_tcb_t *b){   m_uint64_t pc;   int i;   pc = b->start_pc+((b->mips_trans_pos-1)<<2);   for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++)      if (pc == cpu->breakpoints[i]) {         mips64_emit_breakpoint(b);         break;      }}#endif /* BREAKPOINT_ENABLE *//* Get host pointer for the physical address */static inline void *physmem_get_hptr(vm_instance_t *vm,m_uint64_t paddr,                                     u_int op_size,u_int op_type,                                     m_uint64_t *data){   struct vdevice *dev;   m_uint32_t offset;   void *ptr;   int cow;   if (!(dev = dev_lookup(vm,paddr,FALSE)))      return NULL;   if (dev->flags & VDEVICE_FLAG_SPARSE) {      ptr = (void *)dev_sparse_get_host_addr(vm,dev,paddr,op_type,&cow);      if (!ptr) return NULL;      return(ptr + (paddr & VM_PAGE_IMASK));   }   if ((dev->host_addr != 0) && !(dev->flags & VDEVICE_FLAG_NO_MTS_MMAP))      return((void *)dev->host_addr + (paddr - dev->phys_addr));   if (op_size == 0)      return NULL;   offset = paddr - dev->phys_addr;   return(dev->handler(vm->boot_cpu,dev,offset,op_size,op_type,data));}/* Check if an instruction is in a delay slot or not */int mips64_jit_is_delay_slot(mips64_jit_tcb_t *b,m_uint64_t pc){      struct mips64_insn_tag *tag;   m_uint32_t offset,insn;   offset = (pc - b->start_pc) >> 2;   if (!offset)      return(FALSE);   /* Fetch the previous instruction to determine if it is a jump */   insn = vmtoh32(b->mips_code[offset-1]);   tag = insn_tag_find(insn);   assert(tag != NULL);   return(!tag->delay_slot);}/* Fetch a MIPS instruction and emit corresponding translated code */struct mips64_insn_tag *mips64_jit_fetch_and_emit(cpu_mips_t *cpu,                                                  mips64_jit_tcb_t *block,                                                  int delay_slot){   struct mips64_insn_tag *tag;   mips_insn_t code;   code = insn_fetch(block);   tag = insn_tag_find(code);   assert(tag);   /* Branch-delay slot is in another page: slow exec */   if ((block->mips_trans_pos == (MIPS_INSN_PER_PAGE-1)) && !tag->delay_slot) {      block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;      mips64_set_pc(block,block->start_pc + (block->mips_trans_pos << 2));      mips64_emit_single_step(block,code);       mips64_jit_tcb_push_epilog(block);      block->mips_trans_pos++;      return tag;   }   if (delay_slot && !tag->delay_slot) {      mips64_emit_invalid_delay_slot(block);      return NULL;   }   if (!delay_slot)      block->jit_insn_ptr[block->mips_trans_pos] = block->jit_ptr;   if (delay_slot != 2)      block->mips_trans_pos++;#if DEBUG_INSN_PERF_CNT   mips64_inc_perf_counter(block);#endif   if (!delay_slot) {      /* Check for IRQs + Increment count register before jumps */      if (!tag->delay_slot) {         mips64_inc_cp0_count_reg(block);         mips64_check_pending_irq(block);      }   }#if BREAKPOINT_ENABLE   if (cpu->breakpoints_enabled)      insn_emit_breakpoint(cpu,block);#endif   tag->emit(cpu,block,code);   return tag;}/* Add end of JIT block */static void mips64_jit_tcb_add_end(mips64_jit_tcb_t *b){   mips64_set_pc(b,b->start_pc+(b->mips_trans_pos<<2));   mips64_jit_tcb_push_epilog(b);}/* Record a patch to apply in a compiled block */int mips64_jit_tcb_record_patch(mips64_jit_tcb_t *block,u_char *jit_ptr,                                m_uint64_t vaddr){   struct mips64_jit_patch_table *ipt = block->patch_table;   struct mips64_insn_patch *patch;   /* pc must be 32-bit aligned */   if (vaddr & 0x03) {      fprintf(stderr,"Block 0x%8.8llx: trying to record an invalid PC "              "(0x%8.8llx) - mips_trans_pos=%d.\n",

⌨️ 快捷键说明

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