--- upstream/dynamips-0.2.7-RC2/ppc32_jit.h 2007/10/06 16:24:54 8 +++ upstream/dynamips-0.2.7-RC3/ppc32_jit.h 2007/10/06 16:26:06 9 @@ -22,7 +22,7 @@ #define PPC_JIT_BUFSIZE 32768 /* Maximum number of X86 chunks */ -#define PPC_JIT_MAX_CHUNKS 32 +#define PPC_JIT_MAX_CHUNKS 64 /* Size of hash for IA lookup */ #define PPC_JIT_IA_HASH_BITS 17 @@ -34,19 +34,23 @@ #define PPC_JIT_PHYS_HASH_MASK ((1 << PPC_JIT_PHYS_HASH_BITS) - 1) #define PPC_JIT_PHYS_HASH_SIZE (1 << PPC_JIT_PHYS_HASH_BITS) +#define PPC_JIT_TARGET_BITMAP_INDEX(x) (((x) >> 7) & 0x1F) +#define PPC_JIT_TARGET_BITMAP_POS(x) (((x) >> 2) & 0x1F) + /* Instruction jump patch */ struct ppc32_insn_patch { + struct ppc32_insn_patch *next; u_char *jit_insn; - m_uint64_t ppc_ia; + m_uint32_t ppc_ia; }; /* Instruction patch table */ #define PPC32_INSN_PATCH_TABLE_SIZE 32 -struct ppc32_jit_patch_table { +struct ppc32_jit_patch_table { + struct ppc32_jit_patch_table *next; struct ppc32_insn_patch patches[PPC32_INSN_PATCH_TABLE_SIZE]; u_int cur_patch; - struct ppc32_jit_patch_table *next; }; /* PPC32 translated code block */ @@ -66,6 +70,10 @@ m_uint32_t phys_page; m_uint32_t phys_hash; ppc32_jit_tcb_t **phys_pprev,*phys_next; + + /* 1024 instructions per page, one bit per instruction */ + m_uint32_t target_bitmap[32]; + m_uint32_t target_undef_cnt; #if DEBUG_BLOCK_TIMESTAMP m_uint64_t tm_first_use,tm_last_use; @@ -78,6 +86,30 @@ m_uint32_t mask,value; }; +/* Mark the specified IA as a target for further recompiling */ +static inline void +ppc32_jit_tcb_set_target_bit(ppc32_jit_tcb_t *b,m_uint32_t ia) +{ + int index,pos; + + index = PPC_JIT_TARGET_BITMAP_INDEX(ia); + pos = PPC_JIT_TARGET_BITMAP_POS(ia); + + b->target_bitmap[index] |= 1 << pos; +} + +/* Returns TRUE if the specified IA is in the target bitmap */ +static inline int +ppc32_jit_tcb_get_target_bit(ppc32_jit_tcb_t *b,m_uint32_t ia) +{ + int index,pos; + + index = PPC_JIT_TARGET_BITMAP_INDEX(ia); + pos = PPC_JIT_TARGET_BITMAP_POS(ia); + + return(b->target_bitmap[index] & (1 << pos)); +} + /* Get the JIT instruction pointer in a translated block */ static forced_inline u_char *ppc32_jit_tcb_get_host_ptr(ppc32_jit_tcb_t *b,m_uint32_t vaddr) @@ -143,8 +175,140 @@ return NULL; } +/* ======================================================================== */ +/* JIT emit operations (generic). */ +/* ======================================================================== */ + +/* Indicate registers modified by ppc32_update_cr() functions */ +extern void ppc32_update_cr_set_altered_hreg(cpu_ppc_t *cpu); + +/* Set opcode */ +static inline void ppc32_op_set(cpu_ppc_t *cpu,jit_op_t *op) +{ + cpu_gen_t *c = cpu->gen; + *c->jit_op_current = op; + c->jit_op_current = &op->next; +} + +/* EMIT_BASIC_OPCODE */ +static inline void ppc32_op_emit_basic_opcode(cpu_ppc_t *cpu,u_int opcode) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,opcode); + ppc32_op_set(cpu,op); +} + +/* Trash the specified host register */ +static inline void ppc32_op_emit_alter_host_reg(cpu_ppc_t *cpu,int host_reg) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_ALTER_HOST_REG); + op->param[0] = host_reg; + ppc32_op_set(cpu,op); +} + +/* EMIT_INSN_OUTPUT */ +static inline jit_op_t * +ppc32_op_emit_insn_output(cpu_ppc_t *cpu,u_int size_index,char *insn_name) +{ + jit_op_t *op = jit_op_get(cpu->gen,size_index,JIT_OP_INSN_OUTPUT); + op->arg_ptr = NULL; + op->insn_name = insn_name; + ppc32_op_set(cpu,op); + return op; +} + +/* EMIT_LOAD_GPR */ +static inline +void ppc32_op_emit_load_gpr(cpu_ppc_t *cpu,int host_reg,int ppc_reg) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_LOAD_GPR); + op->param[0] = host_reg; + op->param[1] = ppc_reg; + op->param[2] = host_reg; + ppc32_op_set(cpu,op); +} + +/* EMIT_STORE_GPR */ +static inline +void ppc32_op_emit_store_gpr(cpu_ppc_t *cpu,int ppc_reg,int host_reg) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_STORE_GPR); + op->param[0] = host_reg; + op->param[1] = ppc_reg; + op->param[2] = host_reg; + ppc32_op_set(cpu,op); +} + +/* EMIT_UPDATE_FLAGS */ +static inline +void ppc32_op_emit_update_flags(cpu_ppc_t *cpu,int field,int is_signed) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_UPDATE_FLAGS); + + op->param[0] = field; + op->param[1] = is_signed; + + ppc32_op_set(cpu,op); + ppc32_update_cr_set_altered_hreg(cpu); +} + +/* EMIT_REQUIRE_FLAGS */ +static inline void ppc32_op_emit_require_flags(cpu_ppc_t *cpu,int field) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_REQUIRE_FLAGS); + op->param[0] = field; + ppc32_op_set(cpu,op); +} + +/* EMIT_BRANCH_TARGET */ +static inline void ppc32_op_emit_branch_target(cpu_ppc_t *cpu, + ppc32_jit_tcb_t *b, + m_uint32_t ia) +{ + cpu_gen_t *c = cpu->gen; + jit_op_t *op = jit_op_get(c,0,JIT_OP_BRANCH_TARGET); + u_int pos; + + if ((ia & PPC32_MIN_PAGE_MASK) == b->start_ia) { + pos = (ia & PPC32_MIN_PAGE_IMASK) >> 2; + + /* Insert in head */ + op->next = c->jit_op_array[pos]; + c->jit_op_array[pos] = op; + } +} + +/* EMIT_SET_HOST_REG_IMM32 */ +static inline void +ppc32_op_emit_set_host_reg_imm32(cpu_ppc_t *cpu,int reg,m_uint32_t val) +{ + jit_op_t *op = jit_op_get(cpu->gen,0,JIT_OP_SET_HOST_REG_IMM32); + op->param[0] = reg; + op->param[1] = val; + ppc32_op_set(cpu,op); +} + +/* ======================================================================== */ +/* JIT operations with implementations specific to target CPU */ +void ppc32_op_insn_output(ppc32_jit_tcb_t *b,jit_op_t *op); +void ppc32_op_load_gpr(ppc32_jit_tcb_t *b,jit_op_t *op); +void ppc32_op_store_gpr(ppc32_jit_tcb_t *b,jit_op_t *op); +void ppc32_op_update_flags(ppc32_jit_tcb_t *b,jit_op_t *op); +void ppc32_op_move_host_reg(ppc32_jit_tcb_t *b,jit_op_t *op); +void ppc32_op_set_host_reg_imm32(ppc32_jit_tcb_t *b,jit_op_t *op); + +/* Set the Instruction Address (IA) register */ +void ppc32_set_ia(u_char **ptr,m_uint32_t new_ia); + +/* Jump to the next page */ +void ppc32_set_page_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b); + +/* Increment the number of executed instructions (performance debugging) */ +void ppc32_inc_perf_counter(ppc32_jit_tcb_t *b); + +/* ======================================================================== */ + /* Virtual Breakpoint */ -void ppc32_emit_breakpoint(ppc32_jit_tcb_t *b); +void ppc32_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b); /* Initialize instruction lookup table */ void ppc32_jit_create_ilt(void); @@ -163,8 +327,8 @@ ppc32_jit_tcb_t *block); /* Record a patch to apply in a compiled block */ -int ppc32_jit_tcb_record_patch(ppc32_jit_tcb_t *block,u_char *jit_ptr, - m_uint32_t vaddr); +int ppc32_jit_tcb_record_patch(ppc32_jit_tcb_t *block,jit_op_t *iop, + u_char *jit_ptr,m_uint32_t vaddr); /* Free an instruction block */ void ppc32_jit_tcb_free(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block, @@ -174,7 +338,28 @@ int ppc32_jit_tcb_local_addr(ppc32_jit_tcb_t *block,m_uint32_t vaddr, u_char **jit_addr); +/* Recompile a page */ +int ppc32_jit_tcb_recompile(cpu_ppc_t *cpu,ppc32_jit_tcb_t *block); + /* Execute compiled PowerPC code */ void *ppc32_jit_run_cpu(cpu_gen_t *gen); +/* Start register allocation sequence */ +void ppc32_jit_start_hreg_seq(cpu_ppc_t *cpu,char *insn); + +/* Close register allocation sequence */ +void ppc32_jit_close_hreg_seq(cpu_ppc_t *cpu); + +/* Insert a reg map as head of list (as MRU element) */ +void ppc32_jit_insert_hreg_mru(cpu_ppc_t *cpu,struct hreg_map *map); + +/* Allocate an host register */ +int ppc32_jit_alloc_hreg(cpu_ppc_t *cpu,int ppc_reg); + +/* Force allocation of an host register */ +int ppc32_jit_alloc_hreg_forced(cpu_ppc_t *cpu,int hreg); + +/* Initialize register mapping */ +void ppc32_jit_init_hreg_mapping(cpu_ppc_t *cpu); + #endif