82 |
x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(MIPS_GPR_RA)+4,X86_EDX,4); |
x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(MIPS_GPR_RA)+4,X86_EDX,4); |
83 |
} |
} |
84 |
|
|
85 |
|
/* |
86 |
|
* Try to branch directly to the specified JIT block without returning to |
87 |
|
* main loop. |
88 |
|
*/ |
89 |
|
static void mips64_try_direct_far_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b, |
90 |
|
m_uint64_t new_pc) |
91 |
|
{ |
92 |
|
m_uint64_t new_page; |
93 |
|
m_uint32_t pc_hash,pc_offset; |
94 |
|
u_char *test1,*test2,*test3,*test4; |
95 |
|
|
96 |
|
new_page = new_pc & MIPS_MIN_PAGE_MASK; |
97 |
|
pc_offset = (new_pc & MIPS_MIN_PAGE_IMASK) >> 2; |
98 |
|
pc_hash = mips64_jit_get_pc_hash(new_pc); |
99 |
|
|
100 |
|
/* Get JIT block info in %edx */ |
101 |
|
x86_mov_reg_membase(b->jit_ptr,X86_EBX, |
102 |
|
X86_EDI,OFFSET(cpu_mips_t,exec_blk_map),4); |
103 |
|
x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EBX,pc_hash*sizeof(void *),4); |
104 |
|
|
105 |
|
/* no JIT block found ? */ |
106 |
|
x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX); |
107 |
|
test1 = b->jit_ptr; |
108 |
|
x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); |
109 |
|
|
110 |
|
/* Check block PC (lower 32-bits first) */ |
111 |
|
x86_mov_reg_imm(b->jit_ptr,X86_EAX,(m_uint32_t)new_page); |
112 |
|
x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_EDX, |
113 |
|
OFFSET(mips64_jit_tcb_t,start_pc)); |
114 |
|
test2 = b->jit_ptr; |
115 |
|
x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); |
116 |
|
|
117 |
|
/* Check higher bits... */ |
118 |
|
x86_mov_reg_imm(b->jit_ptr,X86_ECX,new_page >> 32); |
119 |
|
x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_ECX,X86_EDX, |
120 |
|
OFFSET(mips64_jit_tcb_t,start_pc)+4); |
121 |
|
test3 = b->jit_ptr; |
122 |
|
x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); |
123 |
|
|
124 |
|
/* Jump to the code */ |
125 |
|
x86_mov_reg_membase(b->jit_ptr,X86_ESI, |
126 |
|
X86_EDX,OFFSET(mips64_jit_tcb_t,jit_insn_ptr),4); |
127 |
|
x86_mov_reg_membase(b->jit_ptr,X86_EBX, |
128 |
|
X86_ESI,pc_offset * sizeof(void *),4); |
129 |
|
|
130 |
|
x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); |
131 |
|
test4 = b->jit_ptr; |
132 |
|
x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); |
133 |
|
x86_jump_reg(b->jit_ptr,X86_EBX); |
134 |
|
|
135 |
|
/* Returns to caller... */ |
136 |
|
x86_patch(test1,b->jit_ptr); |
137 |
|
x86_patch(test2,b->jit_ptr); |
138 |
|
x86_patch(test3,b->jit_ptr); |
139 |
|
x86_patch(test4,b->jit_ptr); |
140 |
|
|
141 |
|
mips64_set_pc(b,new_pc); |
142 |
|
mips64_jit_tcb_push_epilog(b); |
143 |
|
} |
144 |
|
|
145 |
/* Set Jump */ |
/* Set Jump */ |
146 |
static void mips64_set_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b, |
static void mips64_set_jump(cpu_mips_t *cpu,mips64_jit_tcb_t *b, |
147 |
m_uint64_t new_pc,int local_jump) |
m_uint64_t new_pc,int local_jump) |
156 |
if (jump_ptr) { |
if (jump_ptr) { |
157 |
x86_jump_code(b->jit_ptr,jump_ptr); |
x86_jump_code(b->jit_ptr,jump_ptr); |
158 |
} else { |
} else { |
159 |
|
/* Never jump directly to code in a delay slot */ |
160 |
|
if (mips64_jit_is_delay_slot(b,new_pc)) { |
161 |
|
mips64_set_pc(b,new_pc); |
162 |
|
mips64_jit_tcb_push_epilog(b); |
163 |
|
return; |
164 |
|
} |
165 |
|
|
166 |
mips64_jit_tcb_record_patch(b,b->jit_ptr,new_pc); |
mips64_jit_tcb_record_patch(b,b->jit_ptr,new_pc); |
167 |
x86_jump32(b->jit_ptr,0); |
x86_jump32(b->jit_ptr,0); |
168 |
} |
} |
169 |
} else { |
} else { |
170 |
/* save PC */ |
if (cpu->exec_blk_direct_jump) { |
171 |
mips64_set_pc(b,new_pc); |
/* Block lookup optimization */ |
172 |
|
mips64_try_direct_far_jump(cpu,b,new_pc); |
173 |
/* address is in another block, for now, returns to caller */ |
} else { |
174 |
mips64_jit_tcb_push_epilog(b); |
mips64_set_pc(b,new_pc); |
175 |
|
mips64_jit_tcb_push_epilog(b); |
176 |
|
} |
177 |
} |
} |
178 |
} |
} |
179 |
|
|
227 |
memop_fast_access op_handler) |
memop_fast_access op_handler) |
228 |
{ |
{ |
229 |
m_uint64_t val = sign_extend(offset,16); |
m_uint64_t val = sign_extend(offset,16); |
230 |
u_char *test1,*test2,*test3,*p_exception,*p_exit; |
u_char *test1,*test2,*test3,*p_exit; |
231 |
|
|
232 |
test3 = NULL; |
test3 = NULL; |
233 |
|
|
310 |
x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); |
x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); |
311 |
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
312 |
|
|
|
/* 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); |
|
|
|
|
313 |
x86_patch(p_exit,b->jit_ptr); |
x86_patch(p_exit,b->jit_ptr); |
|
x86_patch(p_exception,b->jit_ptr); |
|
314 |
} |
} |
315 |
|
|
316 |
/* Fast memory operation (32-bit) */ |
/* Fast memory operation (32-bit) */ |
320 |
memop_fast_access op_handler) |
memop_fast_access op_handler) |
321 |
{ |
{ |
322 |
m_uint32_t val = sign_extend(offset,16); |
m_uint32_t val = sign_extend(offset,16); |
323 |
u_char *test1,*test2,*p_exception,*p_exit; |
u_char *test1,*test2,*p_exit; |
324 |
|
|
325 |
test2 = NULL; |
test2 = NULL; |
326 |
|
|
398 |
x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); |
x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); |
399 |
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
400 |
|
|
|
/* 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); |
|
|
|
|
401 |
x86_patch(p_exit,b->jit_ptr); |
x86_patch(p_exit,b->jit_ptr); |
|
x86_patch(p_exception,b->jit_ptr); |
|
402 |
} |
} |
403 |
|
|
404 |
/* Fast memory operation */ |
/* Fast memory operation */ |
425 |
int target,int keep_ll_bit) |
int target,int keep_ll_bit) |
426 |
{ |
{ |
427 |
m_uint64_t val = sign_extend(offset,16); |
m_uint64_t val = sign_extend(offset,16); |
|
u_char *test1; |
|
428 |
|
|
429 |
/* Save PC for exception handling */ |
/* Save PC for exception handling */ |
430 |
mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2)); |
mips64_set_pc(b,b->start_pc+((b->mips_trans_pos-1)<<2)); |
456 |
x86_push_reg(b->jit_ptr,X86_EBX); |
x86_push_reg(b->jit_ptr,X86_EBX); |
457 |
x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op)); |
x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op)); |
458 |
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
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); |
|
459 |
} |
} |
460 |
|
|
461 |
/* Coprocessor Register transfert operation */ |
/* Coprocessor Register transfert operation */ |
479 |
/* Virtual Breakpoint */ |
/* Virtual Breakpoint */ |
480 |
void mips64_emit_breakpoint(mips64_jit_tcb_t *b) |
void mips64_emit_breakpoint(mips64_jit_tcb_t *b) |
481 |
{ |
{ |
482 |
|
x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); |
483 |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
484 |
mips64_emit_c_call(b,mips64_run_breakpoint); |
mips64_emit_c_call(b,mips64_run_breakpoint); |
485 |
|
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
486 |
} |
} |
487 |
|
|
488 |
/* Unknown opcode handler */ |
/* Unknown opcode handler */ |
522 |
/* Emit unhandled instruction code */ |
/* Emit unhandled instruction code */ |
523 |
int mips64_emit_invalid_delay_slot(mips64_jit_tcb_t *b) |
int mips64_emit_invalid_delay_slot(mips64_jit_tcb_t *b) |
524 |
{ |
{ |
525 |
|
x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); |
526 |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
527 |
mips64_emit_c_call(b,mips64_invalid_delay_slot); |
mips64_emit_c_call(b,mips64_invalid_delay_slot); |
528 |
|
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
529 |
|
|
530 |
mips64_jit_tcb_push_epilog(b); |
mips64_jit_tcb_push_epilog(b); |
531 |
return(0); |
return(0); |
532 |
} |
} |
533 |
|
|
|
/* Located in external assembly module */ |
|
|
#ifdef FAST_ASM |
|
|
extern void mips64_inc_cp0_cnt_asm(void); |
|
|
#endif |
|
|
|
|
534 |
/* |
/* |
535 |
* Increment count register and trigger the timer IRQ if value in compare |
* Increment count register and trigger the timer IRQ if value in compare |
536 |
* register is the same. |
* register is the same. |
538 |
void mips64_inc_cp0_count_reg(mips64_jit_tcb_t *b) |
void mips64_inc_cp0_count_reg(mips64_jit_tcb_t *b) |
539 |
{ |
{ |
540 |
x86_inc_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,cp0_virt_cnt_reg)); |
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 |
|
541 |
} |
} |
542 |
|
|
543 |
/* Check if there are pending IRQ */ |
/* Check if there are pending IRQ */ |
566 |
/* Increment the number of executed instructions (performance debugging) */ |
/* Increment the number of executed instructions (performance debugging) */ |
567 |
void mips64_inc_perf_counter(mips64_jit_tcb_t *b) |
void mips64_inc_perf_counter(mips64_jit_tcb_t *b) |
568 |
{ |
{ |
569 |
x86_alu_membase_imm(b->jit_ptr,X86_ADD, |
x86_inc_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_mips_t,perf_counter)); |
|
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); |
|
570 |
} |
} |
571 |
|
|
572 |
/* ADD */ |
/* ADD */ |
1387 |
{ |
{ |
1388 |
u_int code = bits(insn,6,25); |
u_int code = bits(insn,6,25); |
1389 |
|
|
1390 |
|
x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); |
1391 |
x86_mov_reg_imm(b->jit_ptr,X86_EDX,code); |
x86_mov_reg_imm(b->jit_ptr,X86_EDX,code); |
1392 |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
1393 |
mips64_emit_basic_c_call(b,mips64_exec_break); |
mips64_emit_basic_c_call(b,mips64_exec_break); |
1394 |
|
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
1395 |
|
|
1396 |
mips64_jit_tcb_push_epilog(b); |
mips64_jit_tcb_push_epilog(b); |
1397 |
return(0); |
return(0); |
1398 |
} |
} |
2792 |
x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); |
x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); |
2793 |
|
|
2794 |
/* Generate trap exception */ |
/* Generate trap exception */ |
2795 |
|
x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); |
2796 |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
2797 |
mips64_emit_c_call(b,mips64_trigger_trap_exception); |
mips64_emit_c_call(b,mips64_trigger_trap_exception); |
2798 |
|
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
2799 |
|
|
2800 |
mips64_jit_tcb_push_epilog(b); |
mips64_jit_tcb_push_epilog(b); |
2801 |
|
|
2802 |
/* end */ |
/* end */ |
2829 |
x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); |
x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); |
2830 |
|
|
2831 |
/* Generate trap exception */ |
/* Generate trap exception */ |
2832 |
|
x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,12); |
2833 |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); |
2834 |
mips64_emit_c_call(b,mips64_trigger_trap_exception); |
mips64_emit_c_call(b,mips64_trigger_trap_exception); |
2835 |
|
x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); |
2836 |
|
|
2837 |
mips64_jit_tcb_push_epilog(b); |
mips64_jit_tcb_push_epilog(b); |
2838 |
|
|
2839 |
/* end */ |
/* end */ |
3038 |
{ mips64_emit_XOR , 0xfc0007ff , 0x00000026, 1 }, |
{ mips64_emit_XOR , 0xfc0007ff , 0x00000026, 1 }, |
3039 |
{ mips64_emit_XORI , 0xfc000000 , 0x38000000, 1 }, |
{ mips64_emit_XORI , 0xfc000000 , 0x38000000, 1 }, |
3040 |
{ mips64_emit_unknown , 0x00000000 , 0x00000000, 1 }, |
{ mips64_emit_unknown , 0x00000000 , 0x00000000, 1 }, |
3041 |
|
{ NULL , 0x00000000 , 0x00000000, 0 }, |
3042 |
}; |
}; |