📄 ppc32_x86_trans.c
字号:
/* EDX = $rb + $ra */ if (update || (ra != 0)) ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EDX,ra); if (update) x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EDX,4); /* ECX = target register */ x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target); /* EAX = CPU instance pointer */ x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); /* Call memory function */ x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); if (update) ppc32_store_gpr(&iop->ob_ptr,ra,X86_ESI);}typedef void (*memop_fast_access)(jit_op_t *iop,int target);/* Fast LBZ */static void ppc32_memop_fast_lbz(jit_op_t *iop,int target){ x86_clear_reg(iop->ob_ptr,X86_ECX); x86_mov_reg_memindex(iop->ob_ptr,X86_ECX,X86_EAX,0,X86_EBX,0,1); ppc32_store_gpr(&iop->ob_ptr,target,X86_ECX);}/* Fast STB */static void ppc32_memop_fast_stb(jit_op_t *iop,int target){ ppc32_load_gpr(&iop->ob_ptr,X86_EDX,target); x86_mov_memindex_reg(iop->ob_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,1);}/* Fast LWZ */static void ppc32_memop_fast_lwz(jit_op_t *iop,int target){ x86_mov_reg_memindex(iop->ob_ptr,X86_EAX,X86_EAX,0,X86_EBX,0,4); x86_bswap(iop->ob_ptr,X86_EAX); ppc32_store_gpr(&iop->ob_ptr,target,X86_EAX);}/* Fast STW */static void ppc32_memop_fast_stw(jit_op_t *iop,int target){ ppc32_load_gpr(&iop->ob_ptr,X86_EDX,target); x86_bswap(iop->ob_ptr,X86_EDX); x86_mov_memindex_reg(iop->ob_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,4);}/* Fast memory operation */static void ppc32_emit_memop_fast(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, int write_op,int opcode, int base,int offset,int target, memop_fast_access op_handler){ m_uint32_t val = sign_extend(offset,16); u_char *test1,*test2,*p_exit,*p_fast_exit; 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_fast"); test2 = NULL; if (val != 0) { /* EBX = sign-extended offset */ ppc32_load_imm(&iop->ob_ptr,X86_EBX,val); /* EBX = GPR[base] + sign-extended offset */ if (base != 0) ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EBX,base); } else { if (base != 0) ppc32_load_gpr(&iop->ob_ptr,X86_EBX,base); else ppc32_load_imm(&iop->ob_ptr,X86_EBX,0); }#if 0 /* ======= zzz ======= */ { u_char *testZ; x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EBX,4); x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK); x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDI, OFFSET(cpu_ppc_t,vtlb[base].vaddr)); testZ = iop->ob_ptr; x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK); x86_mov_reg_membase(iop->ob_ptr,X86_EAX, X86_EDI,OFFSET(cpu_ppc_t,vtlb[base].haddr),4); /* Memory access */ op_handler(iop,target); p_fast_exit = iop->ob_ptr; x86_jump8(iop->ob_ptr,0); x86_patch(testZ,iop->ob_ptr); }#endif /* EAX = mts32_entry index */ x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EBX,4); x86_shift_reg_imm(iop->ob_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT); x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EAX,MTS32_HASH_MASK); /* EDX = mts32_entry */ x86_mov_reg_membase(iop->ob_ptr,X86_EDX, X86_EDI,OFFSET(cpu_ppc_t,mts_cache[PPC32_MTS_DCACHE]), 4); x86_shift_reg_imm(iop->ob_ptr,X86_SHL,X86_EAX,4); x86_alu_reg_reg(iop->ob_ptr,X86_ADD,X86_EDX,X86_EAX); /* Compare virtual page address (ESI = vpage) */ x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EBX,4); x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK); x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDX, OFFSET(mts32_entry_t,gvpa)); test1 = iop->ob_ptr; x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); /* Test if we are writing to a COW page */ if (write_op) { x86_test_membase_imm(iop->ob_ptr,X86_EDX,OFFSET(mts32_entry_t,flags), MTS_FLAG_COW|MTS_FLAG_EXEC); test2 = iop->ob_ptr; x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); } /* EBX = offset in page, EAX = Host Page Address */ x86_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK); x86_mov_reg_membase(iop->ob_ptr,X86_EAX, X86_EDX,OFFSET(mts32_entry_t,hpa),4);#if 0 /* zzz */ { x86_mov_membase_reg(iop->ob_ptr, X86_EDI,OFFSET(cpu_ppc_t,vtlb[base].vaddr), X86_ESI,4); x86_mov_membase_reg(iop->ob_ptr, X86_EDI,OFFSET(cpu_ppc_t,vtlb[base].haddr), X86_EAX,4); }#endif /* Memory access */ op_handler(iop,target); p_exit = iop->ob_ptr; x86_jump8(iop->ob_ptr,0); /* === Slow lookup === */ x86_patch(test1,iop->ob_ptr); if (test2) x86_patch(test2,iop->ob_ptr); /* Update IA (EBX = vaddr) */ ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* EDX = virtual address */ x86_mov_reg_reg(iop->ob_ptr,X86_EDX,X86_EBX,4); /* ECX = target register */ x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target); /* EAX = CPU instance pointer */ x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); /* Call memory function */ x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(opcode)); x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); x86_patch(p_exit,iop->ob_ptr); /* zzz */#if 0 x86_patch(p_fast_exit,iop->ob_ptr);#endif}/* Emit unhandled instruction code */static int ppc32_emit_unknown(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, ppc_insn_t opcode){ u_char *test1; jit_op_t *iop; iop = ppc32_op_emit_insn_output(cpu,3,"unknown"); /* Update IA */ ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* Fallback to non-JIT mode */ x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); x86_mov_reg_imm(iop->ob_ptr,X86_EDX,opcode); ppc32_emit_basic_c_call(&iop->ob_ptr,ppc32_exec_single_insn_ext); x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); 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); /* Signal this as an EOB to reset JIT state */ ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); return(0);}/* Virtual Breakpoint */void ppc32_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b){ jit_op_t *iop; iop = ppc32_op_emit_insn_output(cpu,2,"breakpoint"); x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST); x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); ppc32_emit_c_call(b,iop,ppc32_run_breakpoint); x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); /* Signal this as an EOB to to reset JIT state */ ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);}/* Dump regs */static void ppc32_emit_dump_regs(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b){ jit_op_t *iop; iop = ppc32_op_emit_insn_output(cpu,2,"dump_regs"); x86_mov_reg_membase(iop->ob_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),4); x86_alu_reg_imm(iop->ob_ptr,X86_SUB,X86_ESP,STACK_ADJUST-4); x86_push_reg(iop->ob_ptr,X86_EAX); ppc32_emit_c_call(b,iop,ppc32_dump_regs); x86_alu_reg_imm(iop->ob_ptr,X86_ADD,X86_ESP,STACK_ADJUST); /* Signal this as an EOB to to reset JIT state */ ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB);}/* Increment the number of executed instructions (performance debugging) */void ppc32_inc_perf_counter(cpu_ppc_t *cpu){ jit_op_t *iop; iop = ppc32_op_emit_insn_output(cpu,1,"perf_cnt"); x86_inc_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,perf_counter));}/* ======================================================================== *//* BLR - Branch to Link Register */DECLARE_INSN(BLR){ jit_op_t *iop; int hreg; ppc32_jit_start_hreg_seq(cpu,"blr"); hreg = ppc32_jit_alloc_hreg(cpu,-1); ppc32_op_emit_alter_host_reg(cpu,hreg); iop = ppc32_op_emit_insn_output(cpu,2,"blr"); x86_mov_reg_membase(iop->ob_ptr,hreg,X86_EDI,OFFSET(cpu_ppc_t,lr),4); x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),hreg,4); /* set the return address */ if (insn & 1) ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); ppc32_jit_tcb_push_epilog(&iop->ob_ptr); ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); ppc32_jit_close_hreg_seq(cpu); return(0);}/* BCTR - Branch to Count Register */DECLARE_INSN(BCTR){ jit_op_t *iop; int hreg; ppc32_jit_start_hreg_seq(cpu,"bctr"); hreg = ppc32_jit_alloc_hreg(cpu,-1); ppc32_op_emit_alter_host_reg(cpu,hreg); iop = ppc32_op_emit_insn_output(cpu,2,"bctr"); x86_mov_reg_membase(iop->ob_ptr,hreg,X86_EDI,OFFSET(cpu_ppc_t,ctr),4); x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),hreg,4); /* set the return address */ if (insn & 1) ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); ppc32_jit_tcb_push_epilog(&iop->ob_ptr); ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); ppc32_jit_close_hreg_seq(cpu); return(0);}/* MFLR - Move From Link Register */DECLARE_INSN(MFLR){ int rd = bits(insn,21,25); int hreg_rd; jit_op_t *iop; ppc32_jit_start_hreg_seq(cpu,"mflr"); hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); iop = ppc32_op_emit_insn_output(cpu,1,"mflr"); x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,lr),4); ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); ppc32_jit_close_hreg_seq(cpu); return(0);}/* MTLR - Move To Link Register */DECLARE_INSN(MTLR){ int rs = bits(insn,21,25); int hreg_rs; jit_op_t *iop; ppc32_jit_start_hreg_seq(cpu,"mtlr"); hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); iop = ppc32_op_emit_insn_output(cpu,1,"mtlr"); x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),hreg_rs,4); ppc32_jit_close_hreg_seq(cpu); return(0);}/* MFCTR - Move From Counter Register */DECLARE_INSN(MFCTR){ int rd = bits(insn,21,25); int hreg_rd; jit_op_t *iop; ppc32_jit_start_hreg_seq(cpu,"mfctr"); hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); iop = ppc32_op_emit_insn_output(cpu,1,"mfctr"); x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,ctr),4); ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); ppc32_jit_close_hreg_seq(cpu); return(0);}/* MTCTR - Move To Counter Register */DECLARE_INSN(MTCTR){ int rs = bits(insn,21,25); int hreg_rs; jit_op_t *iop; ppc32_jit_start_hreg_seq(cpu,"mtctr"); hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); iop = ppc32_op_emit_insn_output(cpu,1,"mtctr"); x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr),hreg_rs,4); ppc32_jit_close_hreg_seq(cpu); return(0);}/* MFTBU - Move from Time Base (Up) */DECLARE_INSN(MFTBU){ int rd = bits(insn,21,25); int hreg_rd; jit_op_t *iop; ppc32_jit_start_hreg_seq(cpu,"mftbu"); hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); iop = ppc32_op_emit_insn_output(cpu,1,"mftbu"); x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4); ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); ppc32_jit_close_hreg_seq(cpu); return(0);}#define PPC32_TB_INCREMENT 50/* MFTBL - Move from Time Base (Lo) */DECLARE_INSN(MFTBL){ int rd = bits(insn,21,25); int hreg_rd,hreg_t0; jit_op_t *iop; ppc32_jit_start_hreg_seq(cpu,"mftbl"); hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); iop = ppc32_op_emit_insn_output(cpu,3,"mftbl"); x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,tb),4); /* Increment the time base register */ x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,tb),4); x86_mov_reg_membase(iop->ob_ptr,hreg_t0,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4); x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,PPC32_TB_INCREMENT); x86_alu_reg_imm(iop->ob_ptr,X86_ADC,hreg_t0,0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -