📄 ppc32_amd64_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_amd64_trans.h"#include "memory.h"/* 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, };/* Load a 32 bit immediate value */static inline void ppc32_load_imm(u_char **ptr,u_int reg,m_uint32_t val){ if (val) amd64_mov_reg_imm_size(*ptr,reg,val,4); else amd64_alu_reg_reg_size(*ptr,X86_XOR,reg,reg,4);}/* Set the Instruction Address (IA) register */void ppc32_set_ia(u_char **ptr,m_uint32_t new_ia){ amd64_mov_membase_imm(*ptr,AMD64_R15,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){ amd64_mov_membase_imm(iop->ob_ptr,AMD64_R15,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 %rbx, %rdx */ ppc32_op_emit_alter_host_reg(cpu,AMD64_RBX); ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); ppc32_op_emit_alter_host_reg(cpu,AMD64_RSI); 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 %rdx */ amd64_mov_reg_membase(iop->ob_ptr,AMD64_RBX, AMD64_R15,OFFSET(cpu_ppc_t,exec_blk_map),8); amd64_mov_reg_membase(iop->ob_ptr,AMD64_RDX, AMD64_RBX,ia_hash*sizeof(void *),8); /* no JIT block found ? */ amd64_test_reg_reg(iop->ob_ptr,AMD64_RDX,AMD64_RDX); test1 = iop->ob_ptr; amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); /* Check block IA */ ppc32_load_imm(&iop->ob_ptr,AMD64_RSI,new_page); amd64_alu_reg_membase_size(iop->ob_ptr,X86_CMP,AMD64_RAX,AMD64_RDX, OFFSET(ppc32_jit_tcb_t,start_ia),4); test2 = iop->ob_ptr; amd64_branch8(iop->ob_ptr, X86_CC_NE, 0, 1); /* Jump to the code */ amd64_mov_reg_membase(iop->ob_ptr,AMD64_RSI, AMD64_RDX,OFFSET(ppc32_jit_tcb_t,jit_insn_ptr),8); amd64_mov_reg_membase(iop->ob_ptr,AMD64_RBX, AMD64_RSI,ia_offset * sizeof(void *),8); amd64_test_reg_reg(iop->ob_ptr,AMD64_RBX,AMD64_RBX); test3 = iop->ob_ptr; amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); amd64_jump_reg(iop->ob_ptr,AMD64_RBX); /* Returns to caller... */ amd64_patch(test1,iop->ob_ptr); amd64_patch(test2,iop->ob_ptr); amd64_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); amd64_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){ amd64_mov_reg_membase(*ptr,host_reg,AMD64_R15,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){ amd64_mov_membase_reg(*ptr,AMD64_R15,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){ amd64_alu_reg_membase_size(*ptr,op,host_reg, AMD64_R15,REG_OFFSET(ppc_reg),4);}/* * Update CR from %eflags * %rax, %rdx, %rsi are modified. */static void ppc32_update_cr(ppc32_jit_tcb_t *b,int field,int is_signed){ /* Get status bits from EFLAGS */ amd64_pushfd_size(b->jit_ptr,8); amd64_pop_reg(b->jit_ptr,AMD64_RAX); if (!is_signed) { amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0xFF); amd64_mov_reg_imm_size(b->jit_ptr,AMD64_RDX,eflags_to_cr_unsigned,8); } else { amd64_shift_reg_imm(b->jit_ptr,X86_SHR,AMD64_RAX,6); amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x3F); amd64_mov_reg_imm_size(b->jit_ptr,AMD64_RDX,eflags_to_cr_signed,8); } amd64_mov_reg_memindex(b->jit_ptr,AMD64_RAX,AMD64_RDX,0,AMD64_RAX,2,4);#if 0 /* Check XER Summary of Overflow and report it */ amd64_mov_reg_membase(b->jit_ptr,AMD64_RCX, AMD64_R15,OFFSET(cpu_ppc_t,xer),4); amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RCX,PPC32_XER_SO); amd64_shift_reg_imm(b->jit_ptr,X86_SHR,AMD64_RCX,(field << 2) + 3); amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RDX,AMD64_RCX);#endif /* Store modified CR field */ amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,PPC32_CR_FIELD_OFFSET(field), AMD64_RAX,4);}/* * Update CR0 from %eflags * %eax, %ecx, %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){ ppc32_op_emit_alter_host_reg(cpu,AMD64_RAX); ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX);}/* Basic C call */static forced_inline void ppc32_emit_basic_c_call(u_char **ptr,void *f){ amd64_mov_reg_imm(*ptr,AMD64_RBX,f); amd64_call_reg(*ptr,AMD64_RBX);}/* 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[] = { AMD64_RSI, AMD64_RAX, AMD64_RCX, AMD64_RDX, AMD64_R13, AMD64_R14, AMD64_RDI, -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(AMD64_RBX);}/* ======================================================================== *//* 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;}/* 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)) amd64_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)); /* RSI = sign-extended offset */ ppc32_load_imm(&iop->ob_ptr,AMD64_RSI,val); /* RSI = GPR[base] + sign-extended offset */ if (update || (base != 0)) ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,AMD64_RSI,base); if (update) amd64_mov_reg_reg(iop->ob_ptr,AMD64_R14,AMD64_RSI,4); /* RDX = target register */ amd64_mov_reg_imm(iop->ob_ptr,AMD64_RDX,target); /* RDI = CPU instance pointer */ amd64_mov_reg_reg(iop->ob_ptr,AMD64_RDI,AMD64_R15,8); /* Call memory function */ amd64_call_membase(iop->ob_ptr,AMD64_R15,MEMOP_OFFSET(op)); if (update) ppc32_store_gpr(&iop->ob_ptr,base,AMD64_R14);}/* 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)); /* RSI = $rb */ ppc32_load_gpr(&iop->ob_ptr,AMD64_RSI,rb); /* RSI = GPR[base] + sign-extended offset */ if (update || (ra != 0)) ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,AMD64_RSI,ra); if (update)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -