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

📄 mips64_x86_trans.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Cisco router simulation platform. * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) */#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 <fcntl.h>#include "cpu.h"#include "mips64_jit.h"#include "mips64_x86_trans.h"#include "mips64_cp0.h"#include "memory.h"/* Macros for CPU structure access */#define REG_OFFSET(reg)       (OFFSET(cpu_mips_t,gpr[(reg)]))#define CP0_REG_OFFSET(c0reg) (OFFSET(cpu_mips_t,cp0.reg[(c0reg)]))#define MEMOP_OFFSET(op)      (OFFSET(cpu_mips_t,mem_op_fn[(op)]))#define DECLARE_INSN(name) \   static int mips64_emit_##name(cpu_mips_t *cpu,mips64_jit_tcb_t *b, \                                 mips_insn_t insn)/* Set an IRQ */void mips64_set_irq(cpu_mips_t *cpu,m_uint8_t irq){   m_uint32_t m;   m = (1 << (irq + MIPS_CP0_CAUSE_ISHIFT)) & MIPS_CP0_CAUSE_IMASK;   atomic_or(&cpu->irq_cause,m);}/* Clear an IRQ */void mips64_clear_irq(cpu_mips_t *cpu,m_uint8_t irq){   m_uint32_t m;   m = (1 << (irq + MIPS_CP0_CAUSE_ISHIFT)) & MIPS_CP0_CAUSE_IMASK;   atomic_and(&cpu->irq_cause,~m);   if (!cpu->irq_cause)      cpu->irq_pending = 0;}/* Load a 64 bit immediate value */static inline void mips64_load_imm(mips64_jit_tcb_t *b,                                   u_int hi_reg,u_int lo_reg,                                   m_uint64_t value){   m_uint32_t hi_val = value >> 32;   m_uint32_t lo_val = value & 0xffffffff;   if (lo_val)      x86_mov_reg_imm(b->jit_ptr,lo_reg,lo_val);   else      x86_alu_reg_reg(b->jit_ptr,X86_XOR,lo_reg,lo_reg);      if (hi_val)      x86_mov_reg_imm(b->jit_ptr,hi_reg,hi_val);   else      x86_alu_reg_reg(b->jit_ptr,X86_XOR,hi_reg,hi_reg);}/* Set the Pointer Counter (PC) register */void mips64_set_pc(mips64_jit_tcb_t *b,m_uint64_t new_pc){   x86_mov_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,pc),                       new_pc & 0xFFFFFFFF,4);   x86_mov_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,pc)+4,                       new_pc >> 32,4);}/* Set the Return Address (RA) register */void mips64_set_ra(mips64_jit_tcb_t *b,m_uint64_t ret_pc){   mips64_load_imm(b,X86_EDX,X86_EAX,ret_pc);   x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(MIPS_GPR_RA),X86_EAX,4);   x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(MIPS_GPR_RA)+4,X86_EDX,4);}/*  * Try to branch directly to the specified JIT block without returning to  * main loop. */static void mips64_try_direct_far_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b,                                       m_uint64_t new_pc){   m_uint64_t new_page;   m_uint32_t pc_hash,pc_offset;   u_char *test1,*test2,*test3,*test4;   new_page = new_pc & MIPS_MIN_PAGE_MASK;   pc_offset = (new_pc & MIPS_MIN_PAGE_IMASK) >> 2;   pc_hash = mips64_jit_get_pc_hash(new_pc);   /* Get JIT block info in %edx */   x86_mov_reg_membase(b->jit_ptr,X86_EBX,                       X86_EDI,OFFSET(cpu_mips_t,exec_blk_map),4);   x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EBX,pc_hash*sizeof(void *),4);   /* no JIT block found ? */   x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX);   test1 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   /* Check block PC (lower 32-bits first) */   x86_mov_reg_imm(b->jit_ptr,X86_EAX,(m_uint32_t)new_page);   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_EDX,                       OFFSET(mips64_jit_tcb_t,start_pc));   test2 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1);   /* Check higher bits... */   x86_mov_reg_imm(b->jit_ptr,X86_ECX,new_page >> 32);   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ECX,X86_EDX,                       OFFSET(mips64_jit_tcb_t,start_pc)+4);   test3 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1);   /* Jump to the code */   x86_mov_reg_membase(b->jit_ptr,X86_ESI,                       X86_EDX,OFFSET(mips64_jit_tcb_t,jit_insn_ptr),4);   x86_mov_reg_membase(b->jit_ptr,X86_EBX,                       X86_ESI,pc_offset * sizeof(void *),4);      x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX);   test4 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   x86_jump_reg(b->jit_ptr,X86_EBX);   /* Returns to caller... */   x86_patch(test1,b->jit_ptr);   x86_patch(test2,b->jit_ptr);   x86_patch(test3,b->jit_ptr);   x86_patch(test4,b->jit_ptr);   mips64_set_pc(b,new_pc);   mips64_jit_tcb_push_epilog(b);}/* Set Jump */static void mips64_set_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b,                            m_uint64_t new_pc,int local_jump){         int return_to_caller = FALSE;   u_char *jump_ptr;   if (cpu->sym_trace && !local_jump)      return_to_caller = TRUE;   if (!return_to_caller && mips64_jit_tcb_local_addr(b,new_pc,&jump_ptr)) {      if (jump_ptr) {         x86_jump_code(b->jit_ptr,jump_ptr);      } else {         /* Never jump directly to code in a delay slot */         if (mips64_jit_is_delay_slot(b,new_pc)) {            mips64_set_pc(b,new_pc);            mips64_jit_tcb_push_epilog(b);            return;         }         mips64_jit_tcb_record_patch(b,b->jit_ptr,new_pc);         x86_jump32(b->jit_ptr,0);      }   } else {      if (cpu->exec_blk_direct_jump) {         /* Block lookup optimization */         mips64_try_direct_far_jump(cpu,b,new_pc);      } else {         mips64_set_pc(b,new_pc);         mips64_jit_tcb_push_epilog(b);      }   }}/* Basic C call */static forced_inline void mips64_emit_basic_c_call(mips64_jit_tcb_t *b,void *f){   x86_mov_reg_imm(b->jit_ptr,X86_EBX,f);   x86_call_reg(b->jit_ptr,X86_EBX);}/* Emit a simple call to a C function without any parameter */static void mips64_emit_c_call(mips64_jit_tcb_t *b,void *f){      mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));   mips64_emit_basic_c_call(b,f);}/* Single-step operation */void mips64_emit_single_step(mips64_jit_tcb_t *b,mips_insn_t insn){   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4);   x86_mov_reg_imm(b->jit_ptr,X86_EDX,insn);   mips64_emit_basic_c_call(b,mips64_exec_single_step);}/* Fast memory operation prototype */typedef void (*memop_fast_access)(mips64_jit_tcb_t *b,int target);/* Fast LW */static void mips64_memop_fast_lw(mips64_jit_tcb_t *b,int target){   x86_mov_reg_memindex(b->jit_ptr,X86_EAX,X86_EAX,0,X86_EBX,0,4);   x86_bswap(b->jit_ptr,X86_EAX);   x86_cdq(b->jit_ptr);   x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(target),X86_EAX,4);   x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(target)+4,X86_EDX,4);}/* Fast SW */static void mips64_memop_fast_sw(mips64_jit_tcb_t *b,int target){   x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,REG_OFFSET(target),4);   x86_bswap(b->jit_ptr,X86_EDX);   x86_mov_memindex_reg(b->jit_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,4);}/* Fast memory operation (64-bit) */static void mips64_emit_memop_fast64(mips64_jit_tcb_t *b,int write_op,                                     int opcode,int base,int offset,                                     int target,int keep_ll_bit,                                     memop_fast_access op_handler){   m_uint64_t val = sign_extend(offset,16);   u_char *test1,*test2,*test3,*p_exit;   test3 = NULL;   /* ECX:EBX = sign-extended offset */   mips64_load_imm(b,X86_ECX,X86_EBX,val);   /* ECX:EBX = GPR[base] + sign-extended offset */   x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EBX,X86_EDI,REG_OFFSET(base));   x86_alu_reg_membase(b->jit_ptr,X86_ADC,X86_ECX,X86_EDI,REG_OFFSET(base)+4);   /* EAX = mts32_entry index */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EBX,4);   x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS32_HASH_MASK);   /* EDX = mts32_entry */   x86_mov_reg_membase(b->jit_ptr,X86_EDX,                       X86_EDI,OFFSET(cpu_mips_t,mts_u.mts64_cache),                       4);   x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EAX,5);   x86_alu_reg_reg(b->jit_ptr,X86_ADD,X86_EDX,X86_EAX);   /* Compare virtual page address (ESI = vpage) */   x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EBX,4);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,MIPS_MIN_PAGE_MASK);   /* Compare the high part of the vaddr */   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ECX,X86_EDX,                       OFFSET(mts64_entry_t,gvpa)+4);   test1 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* Compare the low part of the vaddr */   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ESI,X86_EDX,                       OFFSET(mts64_entry_t,gvpa));   test2 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* Test if we are writing to a COW page */   if (write_op) {      x86_test_membase_imm(b->jit_ptr,X86_EDX,OFFSET(mts64_entry_t,flags),                           MTS_FLAG_COW);      test3 = b->jit_ptr;      x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   }   /* EBX = offset in page, EAX = Host Page Address */   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,MIPS_MIN_PAGE_IMASK);   x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDX,OFFSET(mts64_entry_t,hpa),4);   /* Memory access */   op_handler(b,target);    p_exit = b->jit_ptr;   x86_jump8(b->jit_ptr,0);   /* === Slow lookup === */   x86_patch(test1,b->jit_ptr);   x86_patch(test2,b->jit_ptr);   if (test3)      x86_patch(test3,b->jit_ptr);   /* Update PC (ECX:EBX = vaddr) */   x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EBX,4);   mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));   x86_mov_reg_reg(b->jit_ptr,X86_EDX,X86_ESI,4);   /* EBX = target register */   x86_mov_reg_imm(b->jit_ptr,X86_EBX,target);   /* EAX = CPU instance pointer */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4);   /*     * Push parameters on stack and call memory function.    * Keep the stack aligned on a 16-byte boundary for Darwin/x86.    */   x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,8);   x86_push_reg(b->jit_ptr,X86_EBX);   x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode));   x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12);   x86_patch(p_exit,b->jit_ptr);}/* Fast memory operation (32-bit) */static void mips64_emit_memop_fast32(mips64_jit_tcb_t *b,int write_op,                                     int opcode,int base,int offset,                                     int target,int keep_ll_bit,                                     memop_fast_access op_handler){   m_uint32_t val = sign_extend(offset,16);   u_char *test1,*test2,*p_exit;   test2 = NULL;   /* EBX = sign-extended offset */   x86_mov_reg_imm(b->jit_ptr,X86_EBX,val);   /* EBX = GPR[base] + sign-extended offset */   x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EBX,X86_EDI,REG_OFFSET(base));   /* EAX = mts32_entry index */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EBX,4);   x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS32_HASH_MASK);   /* EDX = mts32_entry */   x86_mov_reg_membase(b->jit_ptr,X86_EDX,                       X86_EDI,OFFSET(cpu_mips_t,mts_u.mts32_cache),                       4);   x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EAX,4);   x86_alu_reg_reg(b->jit_ptr,X86_ADD,X86_EDX,X86_EAX);   /* Compare virtual page address (ESI = vpage) */   x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EBX,4);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK);   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ESI,X86_EDX,                       OFFSET(mts32_entry_t,gvpa));   test1 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* Test if we are writing to a COW page */   if (write_op) {      x86_test_membase_imm(b->jit_ptr,X86_EDX,OFFSET(mts32_entry_t,flags),                           MTS_FLAG_COW);      test2 = b->jit_ptr;      x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   }   /* EBX = offset in page, EAX = Host Page Address */   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK);   x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDX,OFFSET(mts32_entry_t,hpa),4);   /* Memory access */   op_handler(b,target);    p_exit = b->jit_ptr;   x86_jump8(b->jit_ptr,0);   /* === Slow lookup === */   x86_patch(test1,b->jit_ptr);   if (test2)      x86_patch(test2,b->jit_ptr);   /* Update PC (EBX = vaddr) */   mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));   /* Sign-extend virtual address and put vaddr in ECX:EDX */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EBX,4);   x86_cdq(b->jit_ptr);   x86_mov_reg_reg(b->jit_ptr,X86_ECX,X86_EDX,4);   x86_mov_reg_reg(b->jit_ptr,X86_EDX,X86_EAX,4);   /* EBX = target register */   x86_mov_reg_imm(b->jit_ptr,X86_EBX,target);   /* EAX = CPU instance pointer */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4);   /*     * Push parameters on stack and call memory function.    * Keep the stack aligned on a 16-byte boundary for Darwin/x86.    */   x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,8);   x86_push_reg(b->jit_ptr,X86_EBX);   x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode));   x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12);   x86_patch(p_exit,b->jit_ptr);}/* Fast memory operation */static void mips64_emit_memop_fast(cpu_mips_t *cpu,mips64_jit_tcb_t *b,                                   int write_op,int opcode,                                   int base,int offset,                                   int target,int keep_ll_bit,                                   memop_fast_access op_handler){   switch(cpu->addr_mode) {      case 32:         mips64_emit_memop_fast32(b,write_op,opcode,base,offset,target,                                  keep_ll_bit,op_handler);         break;      case 64:         mips64_emit_memop_fast64(b,write_op,opcode,base,offset,target,                                  keep_ll_bit,op_handler);         break;   }}/* Memory operation */static void mips64_emit_memop(mips64_jit_tcb_t *b,int op,int base,int offset,                              int target,int keep_ll_bit){   m_uint64_t val = sign_extend(offset,16);   /* Save PC for exception handling */   mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));   if (!keep_ll_bit) {      x86_clear_reg(b->jit_ptr,X86_EAX);      x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,ll_bit),                          X86_EAX,4);   }   /* ECX:EDX = sign-extended offset */   mips64_load_imm(b,X86_ECX,X86_EDX,val);   /* ECX:EDX = GPR[base] + sign-extended offset */   x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EDX,X86_EDI,REG_OFFSET(base));   x86_alu_reg_membase(b->jit_ptr,X86_ADC,X86_ECX,X86_EDI,REG_OFFSET(base)+4);   /* EBX = target register */   x86_mov_reg_imm(b->jit_ptr,X86_EBX,target);      /* EAX = CPU instance pointer */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4);   /*     * Push parameters on stack and call memory function.    * Keep the stack aligned on a 16-byte boundary for Darwin/x86.    */   x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,8);   x86_push_reg(b->jit_ptr,X86_EBX);   x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op));   x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12);}/* Coprocessor Register transfert operation */static void mips64_emit_cp_xfr_op(mips64_jit_tcb_t *b,int rt,int rd,void *f){   /* update pc */   mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));

⌨️ 快捷键说明

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