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

📄 x86_trans.c

📁 思科路由器仿真器,用来仿7200系列得,可以在电脑上模拟路由器-Cisco router simulator, used to fake a 7200 series can be simulated
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Cisco 7200 (Predator) 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 "x86_trans.h"#include "cp0.h"#include "memory.h"/* 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(insn_block_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(insn_block_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(insn_block_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);}/* Set Jump */static void mips64_set_jump(cpu_mips_t *cpu,insn_block_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 && insn_block_local_addr(b,new_pc,&jump_ptr)) {      if (jump_ptr) {         x86_jump_code(b->jit_ptr,jump_ptr);      } else {         insn_block_record_patch(b,b->jit_ptr,new_pc);         x86_jump32(b->jit_ptr,0);      }   } else {      /* save PC */      mips64_set_pc(b,new_pc);      /* address is in another block, for now, returns to caller */      insn_block_push_epilog(b);   }}/* Basic C call */static forced_inline void mips64_emit_basic_c_call(insn_block_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(insn_block_t *b,void *f){      mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));   mips64_emit_basic_c_call(b,f);}/* Fast memory operation prototype */typedef void (*memop_fast_access)(insn_block_t *b,int target);/* Fast LW */static void mips64_memop_fast_lw(insn_block_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(insn_block_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(insn_block_t *b,int op,                                     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,*test4;   u_char *p_exception,*p_exit;   /* 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 = mts64_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,MTS64_HASH_SHIFT);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS64_HASH_MASK);   /* EDX = mts_cache */   x86_mov_reg_membase(b->jit_ptr,X86_EDX,                       X86_EDI,OFFSET(cpu_mips_t,mts_cache),4);   /* ESI = mts64_entry */   x86_mov_reg_memindex(b->jit_ptr,X86_ESI,X86_EDX,0,X86_EAX,2,4);   x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI);   /* slow lookup */   test1 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   /* Compare the high part of the vaddr */   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ECX,X86_ESI,                       OFFSET(mts64_entry_t,start)+4);   test2 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* EAX = entry mask, compare low part of the vaddr */   x86_mov_reg_membase(b->jit_ptr,X86_EAX,                       X86_ESI,OFFSET(mts64_entry_t,mask),4);   x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_EBX);   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_ESI,                       OFFSET(mts64_entry_t,start));   test3 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* Ok, we have the good entry. Test if this is a device */   x86_mov_reg_membase(b->jit_ptr,X86_EAX,                       X86_ESI,OFFSET(mts64_entry_t,action),4);   x86_mov_reg_reg(b->jit_ptr,X86_EDX,X86_EAX,4);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EDX,MTS_DEV_MASK);   test4 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* EAX = action */   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS_ADDR_MASK);   /* Compute offset */   x86_alu_reg_membase(b->jit_ptr,X86_SUB,X86_EBX,                       X86_ESI,OFFSET(mts64_entry_t,start));   /* 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);   x86_patch(test3,b->jit_ptr);   x86_patch(test4,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(op));   x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12);   /* Check for exception */   x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX);   p_exception = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   insn_block_push_epilog(b);   x86_patch(p_exit,b->jit_ptr);   x86_patch(p_exception,b->jit_ptr);}/* Fast memory operation (32-bit) */static void mips64_emit_memop_fast32(insn_block_t *b,int op,                                     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,*test3;   u_char *p_exception,*p_exit;   /* 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 = mts_cache */   x86_mov_reg_membase(b->jit_ptr,X86_EDX,                       X86_EDI,OFFSET(cpu_mips_t,mts_cache),4);   /* ESI = mts32_entry */   x86_mov_reg_memindex(b->jit_ptr,X86_ESI,X86_EDX,0,X86_EAX,2,4);   x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI);   /* slow lookup */   test1 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   /* ECX = entry mask, compare the virtual addresses */   x86_mov_reg_membase(b->jit_ptr,X86_ECX,                       X86_ESI,OFFSET(mts32_entry_t,mask),4);   x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_ECX,X86_EBX);   x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ECX,X86_ESI,                       OFFSET(mts32_entry_t,start));   test2 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* Ok, we have the good entry. Test if this is a device */   x86_mov_reg_membase(b->jit_ptr,X86_EAX,                       X86_ESI,OFFSET(mts32_entry_t,action),4);   x86_mov_reg_reg(b->jit_ptr,X86_EDX,X86_EAX,4);   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EDX,MTS_DEV_MASK);   test3 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1);   /* EAX = action */   x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS_ADDR_MASK);   /* Compute offset */   x86_alu_reg_membase(b->jit_ptr,X86_SUB,X86_EBX,                       X86_ESI,OFFSET(mts32_entry_t,start));   /* 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);   x86_patch(test3,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(op));   x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12);   /* Check for exception */   x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX);   p_exception = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   insn_block_push_epilog(b);   x86_patch(p_exit,b->jit_ptr);   x86_patch(p_exception,b->jit_ptr);}/* Fast memory operation */static void mips64_emit_memop_fast(cpu_mips_t *cpu,insn_block_t *b,int op,                                   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,op,base,offset,target,keep_ll_bit,                                  op_handler);         break;      case 64:         mips64_emit_memop_fast64(b,op,base,offset,target,keep_ll_bit,                                  op_handler);         break;   }}/* Memory operation */static void mips64_emit_memop(insn_block_t *b,int op,int base,int offset,                              int target,int keep_ll_bit){   m_uint64_t val = sign_extend(offset,16);   u_char *test1;   /* 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);   /* Exception ? */   x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX);   test1 = b->jit_ptr;   x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1);   insn_block_push_epilog(b);   x86_patch(test1,b->jit_ptr);}/* Coprocessor Register transfert operation */static void mips64_emit_cp_xfr_op(insn_block_t *b,int rt,int rd,void *f){   /* update pc */   mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2));   /* cp0 register */   x86_mov_reg_imm(b->jit_ptr,X86_ECX,rd);   /* gpr */   x86_mov_reg_imm(b->jit_ptr,X86_EDX,rt);   /* cpu instance */   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4);   mips64_emit_basic_c_call(b,f);}/* Virtual Breakpoint */void mips64_emit_breakpoint(insn_block_t *b){   x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4);   mips64_emit_c_call(b,mips64_run_breakpoint);}/* Unknown opcode handler */static asmlinkage void mips64_unknown_opcode(cpu_mips_t *cpu,m_uint32_t opcode){   printf("MIPS64: unhandled opcode 0x%8.8x at 0x%llx (ra=0x%llx)\n",          opcode,cpu->pc,cpu->gpr[MIPS_GPR_RA]);   mips64_dump_regs(cpu);}

⌨️ 快捷键说明

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