📄 ppc32_x86_trans.c
字号:
/* * 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 + -