18 |
#include "ppc32_x86_trans.h" |
#include "ppc32_x86_trans.h" |
19 |
#include "memory.h" |
#include "memory.h" |
20 |
|
|
21 |
|
/* %esp adjustment (for MacOS X) */ |
22 |
|
#define STACK_ADJUST 12 |
23 |
|
|
24 |
/* ======================================================================= */ |
/* ======================================================================= */ |
25 |
|
|
26 |
/* Macros for CPU structure access */ |
/* Macros for CPU structure access */ |
194 |
if (cpu->sym_trace && !local_jump) |
if (cpu->sym_trace && !local_jump) |
195 |
return_to_caller = TRUE; |
return_to_caller = TRUE; |
196 |
#endif |
#endif |
197 |
|
|
198 |
if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) { |
if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) { |
199 |
ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); |
ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); |
200 |
x86_jump32(iop->ob_ptr,0); |
x86_jump32(iop->ob_ptr,0); |
306 |
ppc32_emit_basic_c_call(&iop->ob_ptr,f); |
ppc32_emit_basic_c_call(&iop->ob_ptr,f); |
307 |
} |
} |
308 |
|
|
|
/* Increment the number of executed instructions (performance debugging) */ |
|
|
void ppc32_inc_perf_counter(ppc32_jit_tcb_t *b) |
|
|
{ |
|
|
x86_alu_membase_imm(b->jit_ptr,X86_ADD, |
|
|
X86_EDI,OFFSET(cpu_ppc_t,perf_counter),1); |
|
|
x86_alu_membase_imm(b->jit_ptr,X86_ADC, |
|
|
X86_EDI,OFFSET(cpu_ppc_t,perf_counter)+4,0); |
|
|
} |
|
|
|
|
309 |
/* ======================================================================== */ |
/* ======================================================================== */ |
310 |
|
|
311 |
/* Initialize register mapping */ |
/* Initialize register mapping */ |
352 |
b->jit_ptr += op->ob_ptr - op->ob_data; |
b->jit_ptr += op->ob_ptr - op->ob_data; |
353 |
|
|
354 |
if ((op->ob_ptr - op->ob_data) >= jit_op_blk_sizes[op->ob_size_index]) { |
if ((op->ob_ptr - op->ob_data) >= jit_op_blk_sizes[op->ob_size_index]) { |
355 |
printf("FAILURE: count=%d, size=%d\n", |
printf("ppc32_op_insn_output: FAILURE: count=%d, size=%d\n", |
356 |
op->ob_ptr - op->ob_data, jit_op_blk_sizes[op->ob_size_index]); |
op->ob_ptr - op->ob_data, jit_op_blk_sizes[op->ob_size_index]); |
357 |
} |
} |
358 |
} |
} |
399 |
int op,int base,int offset,int target,int update) |
int op,int base,int offset,int target,int update) |
400 |
{ |
{ |
401 |
m_uint32_t val = sign_extend(offset,16); |
m_uint32_t val = sign_extend(offset,16); |
|
u_char *test1; |
|
402 |
jit_op_t *iop; |
jit_op_t *iop; |
403 |
|
|
404 |
/* |
/* |
430 |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
431 |
|
|
432 |
/* Call memory function */ |
/* Call memory function */ |
433 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); |
434 |
x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); |
x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); |
435 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); |
436 |
/* Exception ? */ |
|
|
x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); |
|
|
test1 = iop->ob_ptr; |
|
|
x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); |
|
|
ppc32_jit_tcb_push_epilog(&iop->ob_ptr); |
|
|
x86_patch(test1,iop->ob_ptr); |
|
|
|
|
437 |
if (update) |
if (update) |
438 |
ppc32_store_gpr(&iop->ob_ptr,base,X86_ESI); |
ppc32_store_gpr(&iop->ob_ptr,base,X86_ESI); |
439 |
} |
} |
442 |
static void ppc32_emit_memop_idx(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, |
static void ppc32_emit_memop_idx(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, |
443 |
int op,int ra,int rb,int target,int update) |
int op,int ra,int rb,int target,int update) |
444 |
{ |
{ |
|
u_char *test1; |
|
445 |
jit_op_t *iop; |
jit_op_t *iop; |
446 |
|
|
447 |
/* |
/* |
473 |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
474 |
|
|
475 |
/* Call memory function */ |
/* Call memory function */ |
476 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); |
477 |
x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); |
x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); |
478 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); |
479 |
/* Exception ? */ |
|
|
x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); |
|
|
test1 = iop->ob_ptr; |
|
|
x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); |
|
|
ppc32_jit_tcb_push_epilog(&iop->ob_ptr); |
|
|
x86_patch(test1,iop->ob_ptr); |
|
|
|
|
480 |
if (update) |
if (update) |
481 |
ppc32_store_gpr(&iop->ob_ptr,ra,X86_ESI); |
ppc32_store_gpr(&iop->ob_ptr,ra,X86_ESI); |
482 |
} |
} |
521 |
memop_fast_access op_handler) |
memop_fast_access op_handler) |
522 |
{ |
{ |
523 |
m_uint32_t val = sign_extend(offset,16); |
m_uint32_t val = sign_extend(offset,16); |
524 |
u_char *test1,*test2,*p_exception,*p_exit; |
u_char *test1,*test2,*p_exit,*p_fast_exit; |
525 |
jit_op_t *iop; |
jit_op_t *iop; |
526 |
|
|
527 |
/* |
/* |
549 |
ppc32_load_imm(&iop->ob_ptr,X86_EBX,0); |
ppc32_load_imm(&iop->ob_ptr,X86_EBX,0); |
550 |
} |
} |
551 |
|
|
552 |
|
#if 0 |
553 |
|
/* ======= zzz ======= */ |
554 |
|
{ |
555 |
|
u_char *testZ; |
556 |
|
|
557 |
|
x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EBX,4); |
558 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK); |
559 |
|
x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDI, |
560 |
|
OFFSET(cpu_ppc_t,vtlb[base].vaddr)); |
561 |
|
testZ = iop->ob_ptr; |
562 |
|
x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); |
563 |
|
|
564 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK); |
565 |
|
x86_mov_reg_membase(iop->ob_ptr,X86_EAX, |
566 |
|
X86_EDI,OFFSET(cpu_ppc_t,vtlb[base].haddr),4); |
567 |
|
|
568 |
|
/* Memory access */ |
569 |
|
op_handler(iop,target); |
570 |
|
|
571 |
|
p_fast_exit = iop->ob_ptr; |
572 |
|
x86_jump8(iop->ob_ptr,0); |
573 |
|
|
574 |
|
x86_patch(testZ,iop->ob_ptr); |
575 |
|
} |
576 |
|
#endif |
577 |
|
|
578 |
/* EAX = mts32_entry index */ |
/* EAX = mts32_entry index */ |
579 |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EBX,4); |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EBX,4); |
580 |
x86_shift_reg_imm(iop->ob_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT); |
x86_shift_reg_imm(iop->ob_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT); |
609 |
x86_mov_reg_membase(iop->ob_ptr,X86_EAX, |
x86_mov_reg_membase(iop->ob_ptr,X86_EAX, |
610 |
X86_EDX,OFFSET(mts32_entry_t,hpa),4); |
X86_EDX,OFFSET(mts32_entry_t,hpa),4); |
611 |
|
|
612 |
|
#if 0 |
613 |
|
/* zzz */ |
614 |
|
{ |
615 |
|
x86_mov_membase_reg(iop->ob_ptr, |
616 |
|
X86_EDI,OFFSET(cpu_ppc_t,vtlb[base].vaddr), |
617 |
|
X86_ESI,4); |
618 |
|
x86_mov_membase_reg(iop->ob_ptr, |
619 |
|
X86_EDI,OFFSET(cpu_ppc_t,vtlb[base].haddr), |
620 |
|
X86_EAX,4); |
621 |
|
} |
622 |
|
#endif |
623 |
|
|
624 |
/* Memory access */ |
/* Memory access */ |
625 |
op_handler(iop,target); |
op_handler(iop,target); |
626 |
|
|
645 |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
646 |
|
|
647 |
/* Call memory function */ |
/* Call memory function */ |
648 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); |
649 |
x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(opcode)); |
x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(opcode)); |
650 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); |
651 |
/* Check for exception */ |
|
|
x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); |
|
|
p_exception = iop->ob_ptr; |
|
|
x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); |
|
|
ppc32_jit_tcb_push_epilog(&iop->ob_ptr); |
|
|
|
|
652 |
x86_patch(p_exit,iop->ob_ptr); |
x86_patch(p_exit,iop->ob_ptr); |
653 |
x86_patch(p_exception,iop->ob_ptr); |
|
654 |
|
/* zzz */ |
655 |
|
#if 0 |
656 |
|
x86_patch(p_fast_exit,iop->ob_ptr); |
657 |
|
#endif |
658 |
} |
} |
659 |
|
|
660 |
/* Emit unhandled instruction code */ |
/* Emit unhandled instruction code */ |
670 |
ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); |
ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); |
671 |
|
|
672 |
/* Fallback to non-JIT mode */ |
/* Fallback to non-JIT mode */ |
673 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); |
674 |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
675 |
x86_mov_reg_imm(iop->ob_ptr,X86_EDX,opcode); |
x86_mov_reg_imm(iop->ob_ptr,X86_EDX,opcode); |
676 |
|
|
677 |
ppc32_emit_c_call(b,iop,ppc32_exec_single_insn_ext); |
ppc32_emit_basic_c_call(&iop->ob_ptr,ppc32_exec_single_insn_ext); |
678 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); |
679 |
|
|
680 |
x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); |
x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); |
681 |
test1 = iop->ob_ptr; |
test1 = iop->ob_ptr; |
682 |
x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); |
x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); |
696 |
|
|
697 |
iop = ppc32_op_emit_insn_output(cpu,2,"breakpoint"); |
iop = ppc32_op_emit_insn_output(cpu,2,"breakpoint"); |
698 |
|
|
699 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); |
700 |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); |
701 |
ppc32_emit_c_call(b,iop,ppc32_run_breakpoint); |
ppc32_emit_c_call(b,iop,ppc32_run_breakpoint); |
702 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); |
703 |
|
|
704 |
/* Signal this as an EOB to to reset JIT state */ |
/* Signal this as an EOB to to reset JIT state */ |
705 |
ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); |
ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); |
709 |
static void ppc32_emit_dump_regs(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b) |
static void ppc32_emit_dump_regs(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b) |
710 |
{ |
{ |
711 |
jit_op_t *iop; |
jit_op_t *iop; |
712 |
|
|
713 |
iop = ppc32_op_emit_insn_output(cpu,2,"dump_regs"); |
iop = ppc32_op_emit_insn_output(cpu,2,"dump_regs"); |
714 |
|
|
715 |
x86_mov_reg_membase(iop->ob_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),4); |
x86_mov_reg_membase(iop->ob_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),4); |
716 |
|
|
717 |
|
x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST-4); |
718 |
x86_push_reg(iop->ob_ptr,X86_EAX); |
x86_push_reg(iop->ob_ptr,X86_EAX); |
719 |
ppc32_emit_c_call(b,iop,ppc32_dump_regs); |
ppc32_emit_c_call(b,iop,ppc32_dump_regs); |
720 |
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,4); |
x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); |
721 |
|
|
722 |
/* Signal this as an EOB to to reset JIT state */ |
/* Signal this as an EOB to to reset JIT state */ |
723 |
ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); |
ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); |
724 |
} |
} |
725 |
|
|
726 |
|
/* Increment the number of executed instructions (performance debugging) */ |
727 |
|
void ppc32_inc_perf_counter(cpu_ppc_t *cpu) |
728 |
|
{ |
729 |
|
jit_op_t *iop; |
730 |
|
|
731 |
|
iop = ppc32_op_emit_insn_output(cpu,1,"perf_cnt"); |
732 |
|
x86_inc_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,perf_counter)); |
733 |
|
} |
734 |
|
|
735 |
/* ======================================================================== */ |
/* ======================================================================== */ |
736 |
|
|
737 |
/* BLR - Branch to Link Register */ |
/* BLR - Branch to Link Register */ |
3819 |
{ ppc32_emit_BLA , 0xfc000003 , 0x48000003 }, |
{ ppc32_emit_BLA , 0xfc000003 , 0x48000003 }, |
3820 |
{ ppc32_emit_BCC , 0xfe800000 , 0x40800000 }, |
{ ppc32_emit_BCC , 0xfe800000 , 0x40800000 }, |
3821 |
{ ppc32_emit_BC , 0xfc000000 , 0x40000000 }, |
{ ppc32_emit_BC , 0xfc000000 , 0x40000000 }, |
3822 |
{ ppc32_emit_BCLR , 0xfc00fffe , 0x4c000020 }, |
{ ppc32_emit_BCLR , 0xfc00fffe , 0x4c000020 }, |
3823 |
{ ppc32_emit_CMP , 0xfc6007ff , 0x7c000000 }, |
{ ppc32_emit_CMP , 0xfc6007ff , 0x7c000000 }, |
3824 |
{ ppc32_emit_CMPI , 0xfc600000 , 0x2c000000 }, |
{ ppc32_emit_CMPI , 0xfc600000 , 0x2c000000 }, |
3825 |
{ ppc32_emit_CMPL , 0xfc6007ff , 0x7c000040 }, |
{ ppc32_emit_CMPL , 0xfc6007ff , 0x7c000040 }, |