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

📄 ppc32_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 "jit_op.h"#include "ppc32_jit.h"#include "ppc32_x86_trans.h"#include "memory.h"/* %esp adjustment (for MacOS X) */#define STACK_ADJUST  12/* ======================================================================= *//* Macros for CPU structure access */#define REG_OFFSET(reg)   (OFFSET(cpu_ppc_t,gpr[(reg)]))#define MEMOP_OFFSET(op)  (OFFSET(cpu_ppc_t,mem_op_fn[(op)]))#define DECLARE_INSN(name) \   static int ppc32_emit_##name(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, \                                ppc_insn_t insn)/* EFLAGS to Condition Register (CR) field - signed */static m_uint32_t eflags_to_cr_signed[64] = {   0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,    0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,    0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,    0x04, 0x02, 0x08, 0x02, 0x04, 0x02, 0x08, 0x02,    0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,    0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,    0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02,    0x08, 0x02, 0x04, 0x02, 0x08, 0x02, 0x04, 0x02, };/* EFLAGS to Condition Register (CR) field - unsigned */static m_uint32_t eflags_to_cr_unsigned[256] = {   0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08,    0x02, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x08, };/* Emit unhandled instruction code */static int ppc32_emit_unknown(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,                              ppc_insn_t opcode);/* Load a 32 bit immediate value */static forced_inline void ppc32_load_imm(u_char **ptr,u_int reg,m_uint32_t val){   if (val)      x86_mov_reg_imm(*ptr,reg,val);   else      x86_alu_reg_reg(*ptr,X86_XOR,reg,reg);}/* Set the Instruction Address (IA) register */void ppc32_set_ia(u_char **ptr,m_uint32_t new_ia){   x86_mov_membase_imm(*ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),new_ia,4);}/* Set the Link Register (LR) */static void ppc32_set_lr(jit_op_t *iop,m_uint32_t new_lr){     x86_mov_membase_imm(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),new_lr,4);}/*  * Try to branch directly to the specified JIT block without returning to  * main loop. */static void ppc32_try_direct_far_jump(cpu_ppc_t *cpu,jit_op_t *iop,                                      m_uint32_t new_ia){   m_uint32_t new_page,ia_hash,ia_offset;   u_char *test1,*test2,*test3;   /* Indicate that we throw %esi, %edx */   ppc32_op_emit_alter_host_reg(cpu,X86_ESI);   ppc32_op_emit_alter_host_reg(cpu,X86_EDX);   new_page = new_ia & PPC32_MIN_PAGE_MASK;   ia_offset = (new_ia & PPC32_MIN_PAGE_IMASK) >> 2;   ia_hash = ppc32_jit_get_ia_hash(new_ia);   /* Get JIT block info in %edx */   x86_mov_reg_membase(iop->ob_ptr,X86_EBX,                       X86_EDI,OFFSET(cpu_ppc_t,exec_blk_map),4);   x86_mov_reg_membase(iop->ob_ptr,X86_EDX,X86_EBX,ia_hash*sizeof(void *),4);   /* no JIT block found ? */   x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX);   test1 = iop->ob_ptr;   x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1);   /* Check block IA */   x86_mov_reg_imm(iop->ob_ptr,X86_ESI,new_page);   x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDX,                       OFFSET(ppc32_jit_tcb_t,start_ia));   test2 = iop->ob_ptr;   x86_branch8(iop->ob_ptr, X86_CC_NE, 0, 1);   /* Jump to the code */   x86_mov_reg_membase(iop->ob_ptr,X86_ESI,                       X86_EDX,OFFSET(ppc32_jit_tcb_t,jit_insn_ptr),4);   x86_mov_reg_membase(iop->ob_ptr,X86_EBX,                       X86_ESI,ia_offset * sizeof(void *),4);      x86_test_reg_reg(iop->ob_ptr,X86_EBX,X86_EBX);   test3 = iop->ob_ptr;   x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1);   x86_jump_reg(iop->ob_ptr,X86_EBX);   /* Returns to caller... */   x86_patch(test1,iop->ob_ptr);   x86_patch(test2,iop->ob_ptr);   x86_patch(test3,iop->ob_ptr);   ppc32_set_ia(&iop->ob_ptr,new_ia);   ppc32_jit_tcb_push_epilog(&iop->ob_ptr);}/* Set Jump */static void ppc32_set_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,jit_op_t *iop,                           m_uint32_t new_ia,int local_jump){         int return_to_caller = FALSE;   u_char *jump_ptr;#if 0   if (cpu->sym_trace && !local_jump)      return_to_caller = TRUE;#endif         if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) {      ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia);      x86_jump32(iop->ob_ptr,0);   } else {      if (cpu->exec_blk_direct_jump) {         /* Block lookup optimization */         ppc32_try_direct_far_jump(cpu,iop,new_ia);      } else {         ppc32_set_ia(&iop->ob_ptr,new_ia);         ppc32_jit_tcb_push_epilog(&iop->ob_ptr);      }   }}/* Jump to the next page */void ppc32_set_page_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b){   jit_op_t *iop,*op_list = NULL;   cpu->gen->jit_op_current = &op_list;   iop = ppc32_op_emit_insn_output(cpu,4,"set_page_jump");   ppc32_set_jump(cpu,b,iop,b->start_ia + PPC32_MIN_PAGE_SIZE,FALSE);   ppc32_op_insn_output(b,iop);   jit_op_free_list(cpu->gen,op_list);   cpu->gen->jit_op_current = NULL;}/* Load a GPR into the specified host register */static forced_inline void ppc32_load_gpr(u_char **ptr,u_int host_reg,                                         u_int ppc_reg){   x86_mov_reg_membase(*ptr,host_reg,X86_EDI,REG_OFFSET(ppc_reg),4);}/* Store contents for a host register into a GPR register */static forced_inline void ppc32_store_gpr(u_char **ptr,u_int ppc_reg,                                          u_int host_reg){   x86_mov_membase_reg(*ptr,X86_EDI,REG_OFFSET(ppc_reg),host_reg,4);}/* Apply an ALU operation on a GPR register and a host register */static forced_inline void ppc32_alu_gpr(u_char **ptr,u_int op,                                        u_int host_reg,u_int ppc_reg){   x86_alu_reg_membase(*ptr,op,host_reg,X86_EDI,REG_OFFSET(ppc_reg));}/*  * Update CR from %eflags * %eax, %edx, %esi are modified. */static void ppc32_update_cr(ppc32_jit_tcb_t *b,int field,int is_signed){   /* Get status bits from EFLAGS */   if (!is_signed) {      x86_mov_reg_imm(b->jit_ptr,X86_EAX,0);      x86_lahf(b->jit_ptr);      x86_xchg_ah_al(b->jit_ptr);      x86_mov_reg_imm(b->jit_ptr,X86_EDX,eflags_to_cr_unsigned);   } else {      x86_pushfd(b->jit_ptr);      x86_pop_reg(b->jit_ptr,X86_EAX);      x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,6);      x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x3F);      x86_mov_reg_imm(b->jit_ptr,X86_EDX,eflags_to_cr_signed);   }   x86_mov_reg_memindex(b->jit_ptr,X86_EAX,X86_EDX,0,X86_EAX,2,4);   /* Check XER Summary of Overflow and report it */   //x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,xer),4);   //x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_XER_SO);   //x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_ESI,PPC32_XER_SO_BIT);   //x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ESI);   /* Store modified CR field */   x86_mov_membase_reg(b->jit_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(field),                       X86_EAX,4);}/*  * Update CR0 from %eflags * %eax, %edx, %esi are modified. */static void ppc32_update_cr0(ppc32_jit_tcb_t *b){   ppc32_update_cr(b,0,TRUE);}/* Indicate registers modified by ppc32_update_cr() functions */void ppc32_update_cr_set_altered_hreg(cpu_ppc_t *cpu){   /* Throw %eax and %edx, which are modifed by ppc32_update_cr() */   ppc32_op_emit_alter_host_reg(cpu,X86_EAX);   ppc32_op_emit_alter_host_reg(cpu,X86_EDX);}/* Basic C call */static forced_inline void ppc32_emit_basic_c_call(u_char **ptr,void *f){   x86_mov_reg_imm(*ptr,X86_EBX,f);   x86_call_reg(*ptr,X86_EBX);}/* Emit a simple call to a C function without any parameter */static void ppc32_emit_c_call(ppc32_jit_tcb_t *b,jit_op_t *iop,void *f){      ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));   ppc32_emit_basic_c_call(&iop->ob_ptr,f);}/* ======================================================================== *//* Initialize register mapping */void ppc32_jit_init_hreg_mapping(cpu_ppc_t *cpu){   int avail_hregs[] = { X86_ESI, X86_EAX, X86_ECX, X86_EDX, -1 };   struct hreg_map *map;   int i,hreg;   cpu->hreg_map_list = cpu->hreg_lru = NULL;   /* Add the available registers to the map list */   for(i=0;avail_hregs[i]!=-1;i++) {      hreg = avail_hregs[i];      map = &cpu->hreg_map[hreg];      /* Initialize mapping. At the beginning, no PPC reg is mapped */      map->flags = 0;      map->hreg  = hreg;      map->vreg  = -1;      ppc32_jit_insert_hreg_mru(cpu,map);   }   /* Clear PPC registers mapping */   for(i=0;i<PPC32_GPR_NR;i++)      cpu->ppc_reg_map[i] = -1;}/* Allocate a specific temp register */static int ppc32_jit_get_tmp_hreg(cpu_ppc_t *cpu){   return(X86_EBX);}/* ======================================================================== *//* JIT operations (specific to target CPU).                                 *//* ======================================================================== *//* INSN_OUTPUT */void ppc32_op_insn_output(ppc32_jit_tcb_t *b,jit_op_t *op){   op->ob_final = b->jit_ptr;   memcpy(b->jit_ptr,op->ob_data,op->ob_ptr - op->ob_data);   b->jit_ptr += op->ob_ptr - op->ob_data;   if ((op->ob_ptr - op->ob_data) >= jit_op_blk_sizes[op->ob_size_index]) {      printf("ppc32_op_insn_output: FAILURE: count=%d, size=%d\n",             op->ob_ptr - op->ob_data, jit_op_blk_sizes[op->ob_size_index]);   }}/* LOAD_GPR: p[0] = %host_reg, p[1] = %ppc_reg */void ppc32_op_load_gpr(ppc32_jit_tcb_t *b,jit_op_t *op){   if (op->param[0] != JIT_OP_INV_REG)      ppc32_load_gpr(&b->jit_ptr,op->param[0],op->param[1]);}/* STORE_GPR: p[0] = %host_reg, p[1] = %ppc_reg */void ppc32_op_store_gpr(ppc32_jit_tcb_t *b,jit_op_t *op){   if (op->param[0] != JIT_OP_INV_REG)      ppc32_store_gpr(&b->jit_ptr,op->param[1],op->param[0]);}/* UPDATE_FLAGS: p[0] = cr_field, p[1] = is_signed */void ppc32_op_update_flags(ppc32_jit_tcb_t *b,jit_op_t *op){   if (op->param[0] != JIT_OP_INV_REG)      ppc32_update_cr(b,op->param[0],op->param[1]);}/* MOVE_HOST_REG: p[0] = %host_dst_reg, p[1] = %host_src_reg */void ppc32_op_move_host_reg(ppc32_jit_tcb_t *b,jit_op_t *op){   if ((op->param[0] != JIT_OP_INV_REG) && (op->param[1] != JIT_OP_INV_REG))      x86_mov_reg_reg(b->jit_ptr,op->param[0],op->param[1],4);}/* SET_HOST_REG_IMM32: p[0] = %host_reg, p[1] = imm32 */void ppc32_op_set_host_reg_imm32(ppc32_jit_tcb_t *b,jit_op_t *op){   if (op->param[0] != JIT_OP_INV_REG)      ppc32_load_imm(&b->jit_ptr,op->param[0],op->param[1]);}/* ======================================================================== *//* Memory operation */static void ppc32_emit_memop(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,                             int op,int base,int offset,int target,int update){   m_uint32_t val = sign_extend(offset,16);   jit_op_t *iop;   /*     * Since an exception can be triggered, clear JIT state. This allows    * to use branch target tag (we can directly branch on this instruction).    */   ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);   ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);   iop = ppc32_op_emit_insn_output(cpu,5,"memop");   /* Save PC for exception handling */   ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));   /* EDX = sign-extended offset */   ppc32_load_imm(&iop->ob_ptr,X86_EDX,val);   /* EDX = GPR[base] + sign-extended offset */   if (update || (base != 0))      ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EDX,base);   if (update)      x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EDX,4);   /* ECX = target register */   x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target);      /* EAX = CPU instance pointer */   x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4);   /* Call memory function */   x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST);   x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op));   x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST);      if (update)      ppc32_store_gpr(&iop->ob_ptr,base,X86_ESI);}/* Memory operation (indexed) */static void ppc32_emit_memop_idx(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,                                 int op,int ra,int rb,int target,int update){   jit_op_t *iop;   /*     * Since an exception can be triggered, clear JIT state. This allows    * to use branch target tag (we can directly branch on this instruction).    */   ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET);   ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);   iop = ppc32_op_emit_insn_output(cpu,5,"memop_idx");   /* Save PC for exception handling */   ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2));   /* EDX = $rb */   ppc32_load_gpr(&iop->ob_ptr,X86_EDX,rb);

⌨️ 快捷键说明

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