--- upstream/dynamips-0.2.7-RC1/mips64_x86_trans.c 2007/10/06 16:23:47 7 +++ trunk/mips64_x86_trans.c 2007/10/06 16:45:40 12 @@ -82,6 +82,66 @@ x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(MIPS_GPR_RA)+4,X86_EDX,4); } +/* + * Try to branch directly to the specified JIT block without returning to + * main loop. + */ +static void mips64_try_direct_far_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b, + m_uint64_t new_pc) +{ + m_uint64_t new_page; + m_uint32_t pc_hash,pc_offset; + u_char *test1,*test2,*test3,*test4; + + new_page = new_pc & MIPS_MIN_PAGE_MASK; + pc_offset = (new_pc & MIPS_MIN_PAGE_IMASK) >> 2; + pc_hash = mips64_jit_get_pc_hash(new_pc); + + /* Get JIT block info in %edx */ + x86_mov_reg_membase(b->jit_ptr,X86_EBX, + X86_EDI,OFFSET(cpu_mips_t,exec_blk_map),4); + x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EBX,pc_hash*sizeof(void *),4); + + /* no JIT block found ? */ + x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX); + test1 = b->jit_ptr; + x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); + + /* Check block PC (lower 32-bits first) */ + x86_mov_reg_imm(b->jit_ptr,X86_EAX,(m_uint32_t)new_page); + x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_EDX, + OFFSET(mips64_jit_tcb_t,start_pc)); + test2 = b->jit_ptr; + x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); + + /* Check higher bits... */ + x86_mov_reg_imm(b->jit_ptr,X86_ECX,new_page >> 32); + x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ECX,X86_EDX, + OFFSET(mips64_jit_tcb_t,start_pc)+4); + test3 = b->jit_ptr; + x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); + + /* Jump to the code */ + x86_mov_reg_membase(b->jit_ptr,X86_ESI, + X86_EDX,OFFSET(mips64_jit_tcb_t,jit_insn_ptr),4); + x86_mov_reg_membase(b->jit_ptr,X86_EBX, + X86_ESI,pc_offset * sizeof(void *),4); + + x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); + test4 = b->jit_ptr; + x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); + x86_jump_reg(b->jit_ptr,X86_EBX); + + /* Returns to caller... */ + x86_patch(test1,b->jit_ptr); + x86_patch(test2,b->jit_ptr); + x86_patch(test3,b->jit_ptr); + x86_patch(test4,b->jit_ptr); + + mips64_set_pc(b,new_pc); + mips64_jit_tcb_push_epilog(b); +} + /* Set Jump */ static void mips64_set_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b, m_uint64_t new_pc,int local_jump) @@ -96,15 +156,24 @@ if (jump_ptr) { x86_jump_code(b->jit_ptr,jump_ptr); } else { + /* Never jump directly to code in a delay slot */ + if (mips64_jit_is_delay_slot(b,new_pc)) { + mips64_set_pc(b,new_pc); + mips64_jit_tcb_push_epilog(b); + return; + } + mips64_jit_tcb_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 */ - mips64_jit_tcb_push_epilog(b); + if (cpu->exec_blk_direct_jump) { + /* Block lookup optimization */ + mips64_try_direct_far_jump(cpu,b,new_pc); + } else { + mips64_set_pc(b,new_pc); + mips64_jit_tcb_push_epilog(b); + } } } @@ -158,7 +227,7 @@ memop_fast_access op_handler) { m_uint64_t val = sign_extend(offset,16); - u_char *test1,*test2,*test3,*p_exception,*p_exit; + u_char *test1,*test2,*test3,*p_exit; test3 = NULL; @@ -241,14 +310,7 @@ x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); 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); - mips64_jit_tcb_push_epilog(b); - x86_patch(p_exit,b->jit_ptr); - x86_patch(p_exception,b->jit_ptr); } /* Fast memory operation (32-bit) */ @@ -258,7 +320,7 @@ memop_fast_access op_handler) { m_uint32_t val = sign_extend(offset,16); - u_char *test1,*test2,*p_exception,*p_exit; + u_char *test1,*test2,*p_exit; test2 = NULL; @@ -336,14 +398,7 @@ x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); 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); - mips64_jit_tcb_push_epilog(b); - x86_patch(p_exit,b->jit_ptr); - x86_patch(p_exception,b->jit_ptr); } /* Fast memory operation */ @@ -370,7 +425,6 @@ 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)); @@ -402,13 +456,6 @@ 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); - mips64_jit_tcb_push_epilog(b); - x86_patch(test1,b->jit_ptr); } /* Coprocessor Register transfert operation */ @@ -432,8 +479,10 @@ /* Virtual Breakpoint */ void mips64_emit_breakpoint(mips64_jit_tcb_t *b) { + x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_c_call(b,mips64_run_breakpoint); + x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); } /* Unknown opcode handler */ @@ -473,17 +522,15 @@ /* Emit unhandled instruction code */ int mips64_emit_invalid_delay_slot(mips64_jit_tcb_t *b) { + x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_c_call(b,mips64_invalid_delay_slot); + x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); + mips64_jit_tcb_push_epilog(b); return(0); } -/* Located in external assembly module */ -#ifdef FAST_ASM -extern void mips64_inc_cp0_cnt_asm(void); -#endif - /* * Increment count register and trigger the timer IRQ if value in compare * register is the same. @@ -491,15 +538,6 @@ void mips64_inc_cp0_count_reg(mips64_jit_tcb_t *b) { x86_inc_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,cp0_virt_cnt_reg)); - -#if 0 /* TIMER_IRQ */ -#ifdef FAST_ASM - mips64_emit_basic_c_call(b,mips64_inc_cp0_cnt_asm); -#else - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); - mips64_emit_basic_c_call(b,mips64_exec_inc_cp0_cnt); -#endif -#endif } /* Check if there are pending IRQ */ @@ -528,10 +566,7 @@ /* Increment the number of executed instructions (performance debugging) */ void mips64_inc_perf_counter(mips64_jit_tcb_t *b) { - x86_alu_membase_imm(b->jit_ptr,X86_ADD, - X86_EDI,OFFSET(cpu_mips_t,perf_counter),1); - x86_alu_membase_imm(b->jit_ptr,X86_ADC, - X86_EDI,OFFSET(cpu_mips_t,perf_counter)+4,0); + x86_inc_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,perf_counter)); } /* ADD */ @@ -1352,9 +1387,12 @@ { u_int code = bits(insn,6,25); + x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_imm(b->jit_ptr,X86_EDX,code); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_basic_c_call(b,mips64_exec_break); + x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); + mips64_jit_tcb_push_epilog(b); return(0); } @@ -2754,8 +2792,11 @@ x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); /* Generate trap exception */ + x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_c_call(b,mips64_trigger_trap_exception); + x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); + mips64_jit_tcb_push_epilog(b); /* end */ @@ -2788,8 +2829,11 @@ x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); /* Generate trap exception */ + x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); mips64_emit_c_call(b,mips64_trigger_trap_exception); + x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); + mips64_jit_tcb_push_epilog(b); /* end */ @@ -2994,4 +3038,5 @@ { mips64_emit_XOR , 0xfc0007ff , 0x00000026, 1 }, { mips64_emit_XORI , 0xfc000000 , 0x38000000, 1 }, { mips64_emit_unknown , 0x00000000 , 0x00000000, 1 }, + { NULL , 0x00000000 , 0x00000000, 0 }, };