--- upstream/dynamips-0.2.7-RC2/ppc32_x86_trans.c 2007/10/06 16:24:54 8 +++ upstream/dynamips-0.2.7-RC3/ppc32_x86_trans.c 2007/10/06 16:26:06 9 @@ -13,6 +13,7 @@ #include #include "cpu.h" +#include "jit_op.h" #include "ppc32_jit.h" #include "ppc32_x86_trans.h" #include "memory.h" @@ -99,83 +100,88 @@ 0x02, 0x0a, 0x02, 0x0a, 0x02, 0x0a, 0x02, 0x0a, }; -/* Dump regs */ -static void ppc32_emit_dump_regs(ppc32_jit_tcb_t *b); +/* Emit unhandled instruction code */ +static int ppc32_emit_unknown(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, + ppc_insn_t opcode); /* Load a 32 bit immediate value */ -static inline void ppc32_load_imm(ppc32_jit_tcb_t *b,u_int reg,m_uint32_t val) +static forced_inline void ppc32_load_imm(u_char **ptr,u_int reg,m_uint32_t val) { if (val) - x86_mov_reg_imm(b->jit_ptr,reg,val); + x86_mov_reg_imm(*ptr,reg,val); else - x86_alu_reg_reg(b->jit_ptr,X86_XOR,reg,reg); + x86_alu_reg_reg(*ptr,X86_XOR,reg,reg); } /* Set the Instruction Address (IA) register */ -void ppc32_set_ia(ppc32_jit_tcb_t *b,m_uint32_t new_ia) +void ppc32_set_ia(u_char **ptr,m_uint32_t new_ia) { - x86_mov_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),new_ia,4); + x86_mov_membase_imm(*ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),new_ia,4); } /* Set the Link Register (LR) */ -void ppc32_set_lr(ppc32_jit_tcb_t *b,m_uint32_t new_lr) +static void ppc32_set_lr(jit_op_t *iop,m_uint32_t new_lr) { - x86_mov_membase_imm(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),new_lr,4); + x86_mov_membase_imm(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),new_lr,4); } /* * Try to branch directly to the specified JIT block without returning to * main loop. */ -static void ppc32_try_direct_far_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, +static void ppc32_try_direct_far_jump(cpu_ppc_t *cpu,jit_op_t *iop, m_uint32_t new_ia) { m_uint32_t new_page,ia_hash,ia_offset; u_char *test1,*test2,*test3; + /* Indicate that we throw %esi, %edx */ + ppc32_op_emit_alter_host_reg(cpu,X86_ESI); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + new_page = new_ia & PPC32_MIN_PAGE_MASK; ia_offset = (new_ia & PPC32_MIN_PAGE_IMASK) >> 2; ia_hash = ppc32_jit_get_ia_hash(new_ia); /* Get JIT block info in %edx */ - x86_mov_reg_membase(b->jit_ptr,X86_EBX, + x86_mov_reg_membase(iop->ob_ptr,X86_EBX, X86_EDI,OFFSET(cpu_ppc_t,exec_blk_map),4); - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EBX,ia_hash*sizeof(void *),4); + x86_mov_reg_membase(iop->ob_ptr,X86_EDX,X86_EBX,ia_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); + x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX); + test1 = iop->ob_ptr; + x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); /* Check block IA */ - x86_mov_reg_imm(b->jit_ptr,X86_EAX,new_page); - x86_alu_reg_membase(b->jit_ptr,X86_CMP,X86_EAX,X86_EDX, + x86_mov_reg_imm(iop->ob_ptr,X86_ESI,new_page); + x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDX, OFFSET(ppc32_jit_tcb_t,start_ia)); - test2 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_NE, 0, 1); + test2 = iop->ob_ptr; + x86_branch8(iop->ob_ptr, X86_CC_NE, 0, 1); /* Jump to the code */ - x86_mov_reg_membase(b->jit_ptr,X86_ESI, + x86_mov_reg_membase(iop->ob_ptr,X86_ESI, X86_EDX,OFFSET(ppc32_jit_tcb_t,jit_insn_ptr),4); - x86_mov_reg_membase(b->jit_ptr,X86_EBX, + x86_mov_reg_membase(iop->ob_ptr,X86_EBX, X86_ESI,ia_offset * sizeof(void *),4); - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - test3 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_Z, 0, 1); - x86_jump_reg(b->jit_ptr,X86_EBX); + x86_test_reg_reg(iop->ob_ptr,X86_EBX,X86_EBX); + test3 = iop->ob_ptr; + x86_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); + x86_jump_reg(iop->ob_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(test1,iop->ob_ptr); + x86_patch(test2,iop->ob_ptr); + x86_patch(test3,iop->ob_ptr); - ppc32_set_ia(b,new_ia); - ppc32_jit_tcb_push_epilog(b); + ppc32_set_ia(&iop->ob_ptr,new_ia); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); } /* Set Jump */ -static void ppc32_set_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, +static void ppc32_set_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b,jit_op_t *iop, m_uint32_t new_ia,int local_jump) { int return_to_caller = FALSE; @@ -185,44 +191,55 @@ if (cpu->sym_trace && !local_jump) return_to_caller = TRUE; #endif - + if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) { - if (jump_ptr) { - x86_jump_code(b->jit_ptr,jump_ptr); - } else { - ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); - x86_jump32(b->jit_ptr,0); - } + ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); + x86_jump32(iop->ob_ptr,0); } else { if (cpu->exec_blk_direct_jump) { /* Block lookup optimization */ - ppc32_try_direct_far_jump(cpu,b,new_ia); + ppc32_try_direct_far_jump(cpu,iop,new_ia); } else { - ppc32_set_ia(b,new_ia); - ppc32_jit_tcb_push_epilog(b); + ppc32_set_ia(&iop->ob_ptr,new_ia); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); } } } +/* Jump to the next page */ +void ppc32_set_page_jump(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b) +{ + jit_op_t *iop,*op_list = NULL; + + cpu->gen->jit_op_current = &op_list; + + iop = ppc32_op_emit_insn_output(cpu,4,"set_page_jump"); + ppc32_set_jump(cpu,b,iop,b->start_ia + PPC32_MIN_PAGE_SIZE,FALSE); + ppc32_op_insn_output(b,iop); + + jit_op_free_list(cpu->gen,op_list); + cpu->gen->jit_op_current = NULL; +} + /* Load a GPR into the specified host register */ -static forced_inline void ppc32_load_gpr(ppc32_jit_tcb_t *b,u_int host_reg, +static forced_inline void ppc32_load_gpr(u_char **ptr,u_int host_reg, u_int ppc_reg) { - x86_mov_reg_membase(b->jit_ptr,host_reg,X86_EDI,REG_OFFSET(ppc_reg),4); + x86_mov_reg_membase(*ptr,host_reg,X86_EDI,REG_OFFSET(ppc_reg),4); } /* Store contents for a host register into a GPR register */ -static forced_inline void ppc32_store_gpr(ppc32_jit_tcb_t *b,u_int ppc_reg, +static forced_inline void ppc32_store_gpr(u_char **ptr,u_int ppc_reg, u_int host_reg) { - x86_mov_membase_reg(b->jit_ptr,X86_EDI,REG_OFFSET(ppc_reg),host_reg,4); + x86_mov_membase_reg(*ptr,X86_EDI,REG_OFFSET(ppc_reg),host_reg,4); } /* Apply an ALU operation on a GPR register and a host register */ -static forced_inline void ppc32_alu_gpr(ppc32_jit_tcb_t *b,u_int op, +static forced_inline void ppc32_alu_gpr(u_char **ptr,u_int op, u_int host_reg,u_int ppc_reg) { - x86_alu_reg_membase(b->jit_ptr,op,host_reg,X86_EDI,REG_OFFSET(ppc_reg)); + x86_alu_reg_membase(*ptr,op,host_reg,X86_EDI,REG_OFFSET(ppc_reg)); } /* @@ -244,7 +261,7 @@ x86_mov_reg_memindex(b->jit_ptr,X86_EAX,X86_EDX,0,X86_EAX,2,4); /* Check XER Summary of Overflow and report it */ - x86_mov_reg_membase(b->jit_ptr,X86_ESI,X86_EDI,OFFSET(cpu_ppc_t,xer),4); + x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,xer),4); //x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_XER_SO); //x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_ESI,PPC32_XER_SO_BIT); //x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ESI); @@ -256,240 +273,368 @@ /* * Update CR0 from %eflags - * %eax, %ecx, %edx, %esi are modified. + * %eax, %edx, %esi are modified. */ static void ppc32_update_cr0(ppc32_jit_tcb_t *b) { ppc32_update_cr(b,0,TRUE); } +/* Indicate registers modified by ppc32_update_cr() functions */ +void ppc32_update_cr_set_altered_hreg(cpu_ppc_t *cpu) +{ + /* Throw %eax and %edx, which are modifed by ppc32_update_cr() */ + ppc32_op_emit_alter_host_reg(cpu,X86_EAX); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); +} + /* Basic C call */ -static forced_inline void ppc32_emit_basic_c_call(ppc32_jit_tcb_t *b,void *f) +static forced_inline +void ppc32_emit_basic_c_call(u_char **ptr,void *f) { - x86_mov_reg_imm(b->jit_ptr,X86_EBX,f); - x86_call_reg(b->jit_ptr,X86_EBX); + x86_mov_reg_imm(*ptr,X86_EBX,f); + x86_call_reg(*ptr,X86_EBX); } /* Emit a simple call to a C function without any parameter */ -static void ppc32_emit_c_call(ppc32_jit_tcb_t *b,void *f) +static void ppc32_emit_c_call(ppc32_jit_tcb_t *b,jit_op_t *iop,void *f) { - ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); - ppc32_emit_basic_c_call(b,f); + ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); + ppc32_emit_basic_c_call(&iop->ob_ptr,f); +} + +/* 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); +} + +/* ======================================================================== */ + +/* Initialize register mapping */ +void ppc32_jit_init_hreg_mapping(cpu_ppc_t *cpu) +{ + int avail_hregs[] = { X86_ESI, X86_EAX, X86_ECX, X86_EDX, -1 }; + struct hreg_map *map; + int i,hreg; + + cpu->hreg_map_list = cpu->hreg_lru = NULL; + + /* Add the available registers to the map list */ + for(i=0;avail_hregs[i]!=-1;i++) { + hreg = avail_hregs[i]; + map = &cpu->hreg_map[hreg]; + + /* Initialize mapping. At the beginning, no PPC reg is mapped */ + map->flags = 0; + map->hreg = hreg; + map->vreg = -1; + ppc32_jit_insert_hreg_mru(cpu,map); + } + + /* Clear PPC registers mapping */ + for(i=0;ippc_reg_map[i] = -1; +} + +/* Allocate a specific temp register */ +static int ppc32_jit_get_tmp_hreg(cpu_ppc_t *cpu) +{ + return(X86_EBX); +} + +/* ======================================================================== */ +/* JIT operations (specific to target CPU). */ +/* ======================================================================== */ + +/* INSN_OUTPUT */ +void ppc32_op_insn_output(ppc32_jit_tcb_t *b,jit_op_t *op) +{ + op->ob_final = b->jit_ptr; + memcpy(b->jit_ptr,op->ob_data,op->ob_ptr - op->ob_data); + b->jit_ptr += op->ob_ptr - op->ob_data; + + if ((op->ob_ptr - op->ob_data) >= jit_op_blk_sizes[op->ob_size_index]) { + printf("FAILURE: count=%d, size=%d\n", + op->ob_ptr - op->ob_data, jit_op_blk_sizes[op->ob_size_index]); + } +} + +/* LOAD_GPR: p[0] = %host_reg, p[1] = %ppc_reg */ +void ppc32_op_load_gpr(ppc32_jit_tcb_t *b,jit_op_t *op) +{ + if (op->param[0] != JIT_OP_INV_REG) + ppc32_load_gpr(&b->jit_ptr,op->param[0],op->param[1]); } +/* STORE_GPR: p[0] = %host_reg, p[1] = %ppc_reg */ +void ppc32_op_store_gpr(ppc32_jit_tcb_t *b,jit_op_t *op) +{ + if (op->param[0] != JIT_OP_INV_REG) + ppc32_store_gpr(&b->jit_ptr,op->param[1],op->param[0]); +} + +/* UPDATE_FLAGS: p[0] = cr_field, p[1] = is_signed */ +void ppc32_op_update_flags(ppc32_jit_tcb_t *b,jit_op_t *op) +{ + if (op->param[0] != JIT_OP_INV_REG) + ppc32_update_cr(b,op->param[0],op->param[1]); +} + +/* MOVE_HOST_REG: p[0] = %host_dst_reg, p[1] = %host_src_reg */ +void ppc32_op_move_host_reg(ppc32_jit_tcb_t *b,jit_op_t *op) +{ + if ((op->param[0] != JIT_OP_INV_REG) && (op->param[1] != JIT_OP_INV_REG)) + x86_mov_reg_reg(b->jit_ptr,op->param[0],op->param[1],4); +} + +/* SET_HOST_REG_IMM32: p[0] = %host_reg, p[1] = imm32 */ +void ppc32_op_set_host_reg_imm32(ppc32_jit_tcb_t *b,jit_op_t *op) +{ + if (op->param[0] != JIT_OP_INV_REG) + ppc32_load_imm(&b->jit_ptr,op->param[0],op->param[1]); +} + +/* ======================================================================== */ + /* Memory operation */ -static void ppc32_emit_memop(ppc32_jit_tcb_t *b,int op,int base,int offset, - int target,int update) +static void ppc32_emit_memop(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, + int op,int base,int offset,int target,int update) { m_uint32_t val = sign_extend(offset,16); u_char *test1; + 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"); /* Save PC for exception handling */ - ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); + ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* EDX = sign-extended offset */ - ppc32_load_imm(b,X86_EDX,val); + ppc32_load_imm(&iop->ob_ptr,X86_EDX,val); /* EDX = GPR[base] + sign-extended offset */ if (update || (base != 0)) - ppc32_alu_gpr(b,X86_ADD,X86_EDX,base); + ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EDX,base); if (update) - x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EDX,4); + x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EDX,4); /* ECX = target register */ - x86_mov_reg_imm(b->jit_ptr,X86_ECX,target); + x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target); /* EAX = CPU instance pointer */ - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); + x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); /* Call memory function */ - x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op)); + x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); /* 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); - ppc32_jit_tcb_push_epilog(b); - x86_patch(test1,b->jit_ptr); + 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); if (update) - ppc32_store_gpr(b,base,X86_ESI); + ppc32_store_gpr(&iop->ob_ptr,base,X86_ESI); } /* Memory operation (indexed) */ -static void ppc32_emit_memop_idx(ppc32_jit_tcb_t *b,int op,int ra,int rb, - int target,int update) +static void ppc32_emit_memop_idx(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b, + int op,int ra,int rb,int target,int update) { u_char *test1; + 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_idx"); /* Save PC for exception handling */ - ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); + ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* EDX = $rb */ - ppc32_load_gpr(b,X86_EDX,rb); + ppc32_load_gpr(&iop->ob_ptr,X86_EDX,rb); /* EDX = $rb + $ra */ if (update || (ra != 0)) - ppc32_alu_gpr(b,X86_ADD,X86_EDX,ra); + ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,X86_EDX,ra); if (update) - x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EDX,4); + x86_mov_reg_reg(iop->ob_ptr,X86_ESI,X86_EDX,4); /* ECX = target register */ - x86_mov_reg_imm(b->jit_ptr,X86_ECX,target); + x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target); /* EAX = CPU instance pointer */ - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); + x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); /* Call memory function */ - x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(op)); + x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(op)); /* 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); - ppc32_jit_tcb_push_epilog(b); - x86_patch(test1,b->jit_ptr); + 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); if (update) - ppc32_store_gpr(b,ra,X86_ESI); + ppc32_store_gpr(&iop->ob_ptr,ra,X86_ESI); } -typedef void (*memop_fast_access)(ppc32_jit_tcb_t *b,int target); +typedef void (*memop_fast_access)(jit_op_t *iop,int target); /* Fast LBZ */ -static void ppc32_memop_fast_lbz(ppc32_jit_tcb_t *b,int target) +static void ppc32_memop_fast_lbz(jit_op_t *iop,int target) { - x86_clear_reg(b->jit_ptr,X86_ECX); - x86_mov_reg_memindex(b->jit_ptr,X86_ECX,X86_EAX,0,X86_EBX,0,1); - ppc32_store_gpr(b,target,X86_ECX); + 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(ppc32_jit_tcb_t *b,int target) +static void ppc32_memop_fast_stb(jit_op_t *iop,int target) { - ppc32_load_gpr(b,X86_EDX,target); - x86_mov_memindex_reg(b->jit_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,1); + 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(ppc32_jit_tcb_t *b,int target) +static void ppc32_memop_fast_lwz(jit_op_t *iop,int target) { - x86_mov_reg_memindex(b->jit_ptr,X86_EAX,X86_EAX,0,X86_EBX,0,4); - x86_bswap(b->jit_ptr,X86_EAX); - ppc32_store_gpr(b,target,X86_EAX); + 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(ppc32_jit_tcb_t *b,int target) +static void ppc32_memop_fast_stw(jit_op_t *iop,int target) { - ppc32_load_gpr(b,X86_EDX,target); - x86_bswap(b->jit_ptr,X86_EDX); - x86_mov_memindex_reg(b->jit_ptr,X86_EAX,0,X86_EBX,0,X86_EDX,4); + 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(ppc32_jit_tcb_t *b,int write_op,int opcode, +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_exception,*p_exit; + jit_op_t *iop; - test2 = NULL; + /* + * 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); - /* EBX = sign-extended offset */ - ppc32_load_imm(b,X86_EBX,val); + iop = ppc32_op_emit_insn_output(cpu,5,"memop_fast"); - /* EBX = GPR[base] + sign-extended offset */ - if (base != 0) - ppc32_alu_gpr(b,X86_ADD,X86_EBX,base); + 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); + } /* EAX = mts32_entry index */ - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EBX,4); - x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,MTS32_HASH_SHIFT); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,MTS32_HASH_MASK); + 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(b->jit_ptr,X86_EDX, + 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(b->jit_ptr,X86_SHL,X86_EAX,4); - x86_alu_reg_reg(b->jit_ptr,X86_ADD,X86_EDX,X86_EAX); + 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(b->jit_ptr,X86_ESI,X86_EBX,4); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_MASK); + 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(b->jit_ptr,X86_CMP,X86_ESI,X86_EDX, + x86_alu_reg_membase(iop->ob_ptr,X86_CMP,X86_ESI,X86_EDX, OFFSET(mts32_entry_t,gvpa)); - test1 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); + 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(b->jit_ptr,X86_EDX,OFFSET(mts32_entry_t,flags), + x86_test_membase_imm(iop->ob_ptr,X86_EDX,OFFSET(mts32_entry_t,flags), MTS_FLAG_COW|MTS_FLAG_EXEC); - test2 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); + 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(b->jit_ptr,X86_AND,X86_EBX,PPC32_MIN_PAGE_IMASK); - x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDX,OFFSET(mts32_entry_t,hpa),4); + 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); /* Memory access */ - op_handler(b,target); + op_handler(iop,target); - p_exit = b->jit_ptr; - x86_jump8(b->jit_ptr,0); + p_exit = iop->ob_ptr; + x86_jump8(iop->ob_ptr,0); /* === Slow lookup === */ - x86_patch(test1,b->jit_ptr); + x86_patch(test1,iop->ob_ptr); if (test2) - x86_patch(test2,b->jit_ptr); + x86_patch(test2,iop->ob_ptr); /* Update IA (EBX = vaddr) */ - ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); + ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* EDX = virtual address */ - x86_mov_reg_reg(b->jit_ptr,X86_EDX,X86_EBX,4); + x86_mov_reg_reg(iop->ob_ptr,X86_EDX,X86_EBX,4); /* ECX = target register */ - x86_mov_reg_imm(b->jit_ptr,X86_ECX,target); + x86_mov_reg_imm(iop->ob_ptr,X86_ECX,target); /* EAX = CPU instance pointer */ - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); + x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); /* Call memory function */ - x86_call_membase(b->jit_ptr,X86_EDI,MEMOP_OFFSET(opcode)); + x86_call_membase(iop->ob_ptr,X86_EDI,MEMOP_OFFSET(opcode)); /* 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); - ppc32_jit_tcb_push_epilog(b); - - x86_patch(p_exit,b->jit_ptr); - x86_patch(p_exception,b->jit_ptr); -} - -/* Virtual Breakpoint */ -void ppc32_emit_breakpoint(ppc32_jit_tcb_t *b) -{ - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); - ppc32_emit_c_call(b,ppc32_run_breakpoint); -} - -/* Unknown opcode handler */ -static asmlinkage void ppc32_unknown_opcode(cpu_ppc_t *cpu,m_uint32_t opcode) -{ - printf("PPC32: unhandled opcode 0x%8.8x at 0x%8.8x (lr=0x%8.8x)\n", - opcode,cpu->ia,cpu->lr); + 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); - ppc32_dump_regs(cpu->gen); - exit(1); + x86_patch(p_exit,iop->ob_ptr); + x86_patch(p_exception,iop->ob_ptr); } /* Emit unhandled instruction code */ @@ -497,68 +642,58 @@ ppc_insn_t opcode) { u_char *test1; + jit_op_t *iop; -#if 0 - x86_mov_reg_imm(b->jit_ptr,X86_EAX,opcode); - x86_alu_reg_imm(b->jit_ptr,X86_SUB,X86_ESP,4); - x86_push_reg(b->jit_ptr,X86_EAX); - x86_push_reg(b->jit_ptr,X86_EDI); - ppc32_emit_c_call(b,ppc32_unknown_opcode); - x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,12); -#endif + iop = ppc32_op_emit_insn_output(cpu,3,"unknown"); /* Update IA */ - ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); + ppc32_set_ia(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* Fallback to non-JIT mode */ - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDI,4); - x86_mov_reg_imm(b->jit_ptr,X86_EDX,opcode); + x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); + x86_mov_reg_imm(iop->ob_ptr,X86_EDX,opcode); - ppc32_emit_c_call(b,ppc32_exec_single_insn_ext); - 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); - ppc32_jit_tcb_push_epilog(b); + ppc32_emit_c_call(b,iop,ppc32_exec_single_insn_ext); + 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,b->jit_ptr); - return(0); -} + x86_patch(test1,iop->ob_ptr); -/* Dump regs */ -static void ppc32_emit_dump_regs(ppc32_jit_tcb_t *b) -{ - x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),4); - x86_push_reg(b->jit_ptr,X86_EAX); - ppc32_emit_c_call(b,ppc32_dump_regs); - x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESP,4); + /* Signal this as an EOB to reset JIT state */ + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + return(0); } -/* Increment the number of executed instructions (performance debugging) */ -void ppc32_inc_perf_counter(ppc32_jit_tcb_t *b) +/* Virtual Breakpoint */ +void ppc32_emit_breakpoint(cpu_ppc_t *cpu,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); + jit_op_t *iop; + + iop = ppc32_op_emit_insn_output(cpu,2,"breakpoint"); + + x86_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_EDI,4); + ppc32_emit_c_call(b,iop,ppc32_run_breakpoint); + + /* Signal this as an EOB to to reset JIT state */ + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); } -/* Check if there are pending IRQ */ -void ppc32_check_pending_irq(ppc32_jit_tcb_t *b) -{ - u_char *test1; +/* 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"); - /* Check the pending IRQ flag */ - x86_mov_reg_membase(b->jit_ptr,X86_EAX, - X86_EDI,OFFSET(cpu_ppc_t,irq_check),4); - 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); - - /* Save PC */ - ppc32_set_ia(b,b->start_ia+((b->ppc_trans_pos-1)<<2)); - ppc32_jit_tcb_push_epilog(b); + x86_mov_reg_membase(iop->ob_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,gen),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,4); - x86_patch(test1,b->jit_ptr); + /* Signal this as an EOB to to reset JIT state */ + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); } /* ======================================================================== */ @@ -566,28 +701,54 @@ /* BLR - Branch to Link Register */ DECLARE_INSN(BLR) { - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,lr),4); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),X86_EDX,4); + 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(b,b->start_ia + (b->ppc_trans_pos << 2)); + 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_tcb_push_epilog(b); + ppc32_jit_close_hreg_seq(cpu); return(0); } /* BCTR - Branch to Count Register */ DECLARE_INSN(BCTR) { - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,ctr),4); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),X86_EDX,4); + 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(b,b->start_ia + (b->ppc_trans_pos << 2)); + 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_tcb_push_epilog(b); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -595,9 +756,17 @@ DECLARE_INSN(MFLR) { int rd = bits(insn,21,25); - - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,lr),4); - ppc32_store_gpr(b,rd,X86_EDX); + 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); } @@ -605,9 +774,17 @@ 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); - ppc32_load_gpr(b,X86_EDX,rs); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,lr),X86_EDX,4); + 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); } @@ -615,9 +792,18 @@ DECLARE_INSN(MFCTR) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,ctr),4); - ppc32_store_gpr(b,rd,X86_EDX); + 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); } @@ -625,9 +811,17 @@ 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_load_gpr(b,X86_EDX,rs); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr),X86_EDX,4); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -635,9 +829,18 @@ DECLARE_INSN(MFTBU) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4); - ppc32_store_gpr(b,rd,X86_EDX); + 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); } @@ -647,16 +850,28 @@ 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(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,tb),4); - x86_mov_reg_membase(b->jit_ptr,X86_EBX,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,4); - x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_EDX,PPC32_TB_INCREMENT); - x86_alu_reg_imm(b->jit_ptr,X86_ADC,X86_EBX,0); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb),X86_EDX,4); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,X86_EBX,4); + 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); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb),hreg_rd,4); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,tb)+4,hreg_t0,4); - ppc32_store_gpr(b,rd,X86_EDX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -666,15 +881,35 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rd,hreg_ra,hreg_rb; + jit_op_t *iop; /* $rd = $ra + $rb */ - ppc32_load_gpr(b,X86_EBX,ra); - ppc32_alu_gpr(b,X86_ADD,X86_EBX,rb); - ppc32_store_gpr(b,rd,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"add"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"add"); + + if (rd == ra) + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb); + else if (rd == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_ra); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb); + } + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); if (insn & 1) - ppc32_update_cr0(b); - + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -684,22 +919,45 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rd,hreg_ra,hreg_rb,hreg_t0; + jit_op_t *iop; /* $rd = $ra + $rb */ - ppc32_load_gpr(b,X86_EBX,ra); - ppc32_alu_gpr(b,X86_ADD,X86_EBX,rb); - ppc32_store_gpr(b,rd,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"addc"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); /* store the carry flag */ - x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"addc"); + + if (rd == ra) + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb); + else if (rd == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_ra); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb); + } + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t0,FALSE); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x1); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca), + hreg_t0,4); if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); + x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd); + ppc32_op_emit_update_flags(cpu,0,TRUE); } - + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -709,31 +967,49 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_ra,hreg_rb,hreg_rd,hreg_t0,hreg_t1; + jit_op_t *iop; - /* $ra + carry */ - ppc32_load_gpr(b,X86_ESI,ra); - x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_ESI, - X86_EDI,OFFSET(cpu_ppc_t,xer_ca)); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); + ppc32_jit_start_hreg_seq(cpu,"adde"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - /* add $rb */ - ppc32_alu_gpr(b,X86_ADD,X86_ESI,rb); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); - ppc32_store_gpr(b,rd,X86_ESI); + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); - /* store the carry flag */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); + iop = ppc32_op_emit_insn_output(cpu,3,"adde"); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); + /* $t0 = $ra + carry */ + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + + x86_alu_reg_membase(iop->ob_ptr,X86_ADD,hreg_t0, + X86_EDI,OFFSET(cpu_ppc_t,xer_ca)); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4); + + /* $t0 += $rb */ + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1); /* update cr0 */ - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); - ppc32_update_cr0(b); - } + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_t0,hreg_t0); + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -744,13 +1020,31 @@ int ra = bits(insn,16,20); int imm = bits(insn,0,15); m_uint32_t tmp = sign_extend_32(imm,16); + int hreg_rd,hreg_ra; + jit_op_t *iop; + + /* $rd = $ra + imm */ + ppc32_jit_start_hreg_seq(cpu,"addi"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - ppc32_load_imm(b,X86_EBX,tmp); + if (ra != 0) { + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); - if (ra != 0) - x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EBX,X86_EDI,REG_OFFSET(ra)); + iop = ppc32_op_emit_insn_output(cpu,2,"addi"); - ppc32_store_gpr(b,rd,X86_EBX); + if (rd != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp); + } else { + iop = ppc32_op_emit_insn_output(cpu,1,"addi"); + ppc32_load_imm(&iop->ob_ptr,hreg_rd,tmp); + } + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -761,11 +1055,28 @@ int ra = bits(insn,16,20); int imm = bits(insn,0,15); m_uint32_t tmp = sign_extend_32(imm,16); + int hreg_rd,hreg_ra; + jit_op_t *iop; + + /* $rd = $ra + imm */ + ppc32_jit_start_hreg_seq(cpu,"addic"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + + iop = ppc32_op_emit_insn_output(cpu,1,"addic"); + + if (rd != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); - ppc32_load_imm(b,X86_EAX,tmp); - ppc32_alu_gpr(b,X86_ADD,X86_EAX,ra); - ppc32_store_gpr(b,rd,X86_EAX); - x86_set_membase(b->jit_ptr,X86_CC_C,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE); + x86_set_membase(iop->ob_ptr,X86_CC_C, + X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -776,14 +1087,30 @@ int ra = bits(insn,16,20); int imm = bits(insn,0,15); m_uint32_t tmp = sign_extend_32(imm,16); + int hreg_rd,hreg_ra; + jit_op_t *iop; + + /* $rd = $ra + imm */ + ppc32_jit_start_hreg_seq(cpu,"addic."); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + + iop = ppc32_op_emit_insn_output(cpu,1,"addic."); + + if (rd != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); - ppc32_load_imm(b,X86_EAX,tmp); - ppc32_alu_gpr(b,X86_ADD,X86_EAX,ra); - ppc32_store_gpr(b,rd,X86_EAX); - x86_set_membase(b->jit_ptr,X86_CC_C,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE); + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); - x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); - ppc32_update_cr0(b); + x86_set_membase(iop->ob_ptr,X86_CC_C, + X86_EDI,OFFSET(cpu_ppc_t,xer_ca),FALSE); + + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -793,13 +1120,71 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); m_uint32_t imm = bits(insn,0,15); + m_uint32_t tmp = imm << 16; + int hreg_rd,hreg_ra; + jit_op_t *iop; + + /* $rd = $ra + (imm << 16) */ + ppc32_jit_start_hreg_seq(cpu,"addis"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + + if (ra != 0) { + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + + iop = ppc32_op_emit_insn_output(cpu,1,"addis"); + + if (rd != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,tmp); + } else { + //iop = ppc32_op_emit_insn_output(cpu,1,"addis"); + //x86_mov_reg_imm(iop->ob_ptr,hreg_rd,tmp); + ppc32_op_emit_set_host_reg_imm32(cpu,hreg_rd,tmp); + } + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); + return(0); +} + +/* ADDZE */ +DECLARE_INSN(ADDZE) +{ + int rd = bits(insn,21,25); + int ra = bits(insn,16,20); + int hreg_rd,hreg_ra,hreg_t0; + jit_op_t *iop; - ppc32_load_imm(b,X86_EBX,imm << 16); + /* $rd = $ra + xer_ca + set_carry */ + ppc32_jit_start_hreg_seq(cpu,"addze"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); - if (ra != 0) - x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_EBX,X86_EDI,REG_OFFSET(ra)); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); - ppc32_store_gpr(b,rd,X86_EBX); + iop = ppc32_op_emit_insn_output(cpu,2,"addze"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0); + + if (rd != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + x86_alu_reg_membase(iop->ob_ptr,X86_ADD,hreg_rd, + X86_EDI,OFFSET(cpu_ppc_t,xer_ca)); + + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t0,FALSE); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t0,4); + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -809,14 +1194,35 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb; + jit_op_t *iop; + + /* $ra = $rs & $rb */ + ppc32_jit_start_hreg_seq(cpu,"and"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"and"); + + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb); + else if (ra == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rs); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb); + } - ppc32_load_gpr(b,X86_EBX,rs); - ppc32_alu_gpr(b,X86_AND,X86_EBX,rb); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); if (insn & 1) - ppc32_update_cr0(b); + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -826,16 +1232,39 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb,hreg_t0; + jit_op_t *iop; /* $ra = $rs & ~$rb */ - ppc32_load_gpr(b,X86_EBX,rb); - x86_not_reg(b->jit_ptr,X86_EBX); - ppc32_alu_gpr(b,X86_AND,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"andc"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"andc"); + + /* $t0 = ~$rb */ + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4); + x86_not_reg(iop->ob_ptr,hreg_t0); + + /* $ra = $rs & $t0 */ + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_t0); + else { + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_rs); + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); + } + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); if (insn & 1) - ppc32_update_cr0(b); + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -845,13 +1274,28 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); m_uint16_t imm = bits(insn,0,15); + m_uint32_t tmp = imm; + int hreg_rs,hreg_ra; + jit_op_t *iop; /* $ra = $rs & imm */ - ppc32_load_imm(b,X86_EBX,imm); - ppc32_alu_gpr(b,X86_AND,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"andi"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,2,"andi"); - ppc32_update_cr0(b); + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,tmp); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -861,13 +1305,28 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); m_uint32_t imm = bits(insn,0,15); + m_uint32_t tmp = imm << 16; + int hreg_rs,hreg_ra; + jit_op_t *iop; /* $ra = $rs & imm */ - ppc32_load_imm(b,X86_EBX,imm << 16); - ppc32_alu_gpr(b,X86_AND,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"andis"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); - ppc32_update_cr0(b); + iop = ppc32_op_emit_insn_output(cpu,2,"andis"); + + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,tmp); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -875,12 +1334,19 @@ DECLARE_INSN(B) { m_uint32_t offset = bits(insn,2,25); - m_uint64_t new_ia; + m_uint32_t new_ia; + jit_op_t *iop; + + iop = ppc32_op_emit_insn_output(cpu,4,"b"); /* compute the new ia */ - new_ia = b->start_ia + ((b->ppc_trans_pos-1) << 2); + new_ia = b->start_ia + (b->ppc_trans_pos << 2); new_ia += sign_extend(offset << 2,26); - ppc32_set_jump(cpu,b,new_ia,1); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); + + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + ppc32_op_emit_branch_target(cpu,b,new_ia); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); return(0); } @@ -888,11 +1354,18 @@ DECLARE_INSN(BA) { m_uint32_t offset = bits(insn,2,25); - m_uint64_t new_ia; + m_uint32_t new_ia; + jit_op_t *iop; + + iop = ppc32_op_emit_insn_output(cpu,4,"ba"); /* compute the new ia */ new_ia = sign_extend(offset << 2,26); - ppc32_set_jump(cpu,b,new_ia,1); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); + + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + ppc32_op_emit_branch_target(cpu,b,new_ia); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); return(0); } @@ -900,16 +1373,22 @@ DECLARE_INSN(BL) { m_uint32_t offset = bits(insn,2,25); - m_uint64_t new_ia; + m_uint32_t new_ia; + jit_op_t *iop; + + iop = ppc32_op_emit_insn_output(cpu,4,"bl"); /* compute the new ia */ - new_ia = b->start_ia + ((b->ppc_trans_pos-1) << 2); + new_ia = b->start_ia + (b->ppc_trans_pos << 2); new_ia += sign_extend(offset << 2,26); /* set the return address */ - ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); + ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); - ppc32_set_jump(cpu,b,new_ia,1); + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + ppc32_op_emit_branch_target(cpu,b,new_ia); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); return(0); } @@ -917,15 +1396,21 @@ DECLARE_INSN(BLA) { m_uint32_t offset = bits(insn,2,25); - m_uint64_t new_ia; + m_uint32_t new_ia; + jit_op_t *iop; + + iop = ppc32_op_emit_insn_output(cpu,4,"bla"); /* compute the new ia */ new_ia = sign_extend(offset << 2,26); /* set the return address */ - ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); + ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); - ppc32_set_jump(cpu,b,new_ia,1); + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + ppc32_op_emit_branch_target(cpu,b,new_ia); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); return(0); } @@ -935,29 +1420,38 @@ int bo = bits(insn,21,25); int bi = bits(insn,16,20); int bd = bits(insn,2,15); + jit_op_t *iop; u_int cr_field,cr_bit; m_uint32_t new_ia; u_char *jump_ptr; int local_jump; int cond; + ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_JUMP); + + iop = ppc32_op_emit_insn_output(cpu,5,"bcc"); + /* Get the wanted value for the condition bit */ cond = (bo >> 3) & 0x1; /* Set the return address */ - if (insn & 1) - ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); + if (insn & 1) { + ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1)<<2)); + } /* Compute the new ia */ new_ia = sign_extend_32(bd << 2,16); if (!(insn & 0x02)) - new_ia += b->start_ia + ((b->ppc_trans_pos-1) << 2); + new_ia += b->start_ia + (b->ppc_trans_pos << 2); /* Test the condition bit */ cr_field = ppc32_get_cr_field(bi); cr_bit = ppc32_get_cr_bit(bi); - x86_test_membase_imm(b->jit_ptr, + ppc32_op_emit_require_flags(cpu,cr_field); + + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(cr_field), (1 << cr_bit)); @@ -968,19 +1462,16 @@ * page or not. */ if (local_jump) { - if (jump_ptr) { - x86_branch(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,jump_ptr,FALSE); - } else { - ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); - x86_branch32(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,0,FALSE); - } + ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); + x86_branch32(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,0,FALSE); } else { - jump_ptr = b->jit_ptr; - x86_branch32(b->jit_ptr,(cond) ? X86_CC_Z : X86_CC_NZ,0,FALSE); - ppc32_set_jump(cpu,b,new_ia,TRUE); - x86_patch(jump_ptr,b->jit_ptr); + jump_ptr = iop->ob_ptr; + x86_branch32(iop->ob_ptr,(cond) ? X86_CC_Z : X86_CC_NZ,0,FALSE); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); + x86_patch(jump_ptr,iop->ob_ptr); } + ppc32_op_emit_branch_target(cpu,b,new_ia); return(0); } @@ -990,32 +1481,46 @@ int bo = bits(insn,21,25); int bi = bits(insn,16,20); int bd = bits(insn,2,15); + int hreg_t0,hreg_t1; + jit_op_t *iop; u_int cr_field,cr_bit; m_uint32_t new_ia; u_char *jump_ptr; int local_jump; int cond,ctr; + ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_JUMP); + + iop = ppc32_op_emit_insn_output(cpu,5,"bc"); + + ppc32_jit_start_hreg_seq(cpu,"bc"); + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + /* Get the wanted value for the condition bit and CTR value */ cond = (bo >> 3) & 0x1; ctr = (bo >> 1) & 0x1; /* Set the return address */ - if (insn & 1) - ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); + if (insn & 1) { + ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1)<<2)); + } /* Compute the new ia */ new_ia = sign_extend_32(bd << 2,16); if (!(insn & 0x02)) - new_ia += b->start_ia + ((b->ppc_trans_pos-1) << 2); + new_ia += b->start_ia + (b->ppc_trans_pos << 2); - x86_mov_reg_imm(b->jit_ptr,X86_EAX,1); + x86_mov_reg_imm(iop->ob_ptr,hreg_t0,1); /* Decrement the count register */ if (!(bo & 0x04)) { - x86_dec_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr)); - x86_set_reg(b->jit_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,X86_EBX,FALSE); - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_EBX); + x86_dec_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr)); + x86_set_reg(iop->ob_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,hreg_t1,FALSE); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } /* Test the condition bit */ @@ -1023,15 +1528,17 @@ cr_field = ppc32_get_cr_field(bi); cr_bit = ppc32_get_cr_bit(bi); - x86_test_membase_imm(b->jit_ptr, + ppc32_op_emit_require_flags(cpu,cr_field); + + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(cr_field), (1 << cr_bit)); - x86_set_reg(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,X86_ECX,FALSE); - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_ECX); + x86_set_reg(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,hreg_t1,FALSE); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x01); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); local_jump = ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr); @@ -1040,19 +1547,18 @@ * page or not. */ if (local_jump) { - if (jump_ptr) { - x86_branch(b->jit_ptr,X86_CC_NZ,jump_ptr,FALSE); - } else { - ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); - x86_branch32(b->jit_ptr,X86_CC_NZ,0,FALSE); - } + ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); + x86_branch32(iop->ob_ptr,X86_CC_NZ,0,FALSE); } else { - jump_ptr = b->jit_ptr; - x86_branch32(b->jit_ptr,X86_CC_Z,0,FALSE); - ppc32_set_jump(cpu,b,new_ia,TRUE); - x86_patch(jump_ptr,b->jit_ptr); + jump_ptr = iop->ob_ptr; + x86_branch32(iop->ob_ptr,X86_CC_Z,0,FALSE); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); + x86_patch(jump_ptr,iop->ob_ptr); } + ppc32_op_emit_branch_target(cpu,b,new_ia); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1062,11 +1568,21 @@ int bo = bits(insn,21,25); int bi = bits(insn,16,20); int bd = bits(insn,2,15); + int hreg_t0,hreg_t1; + jit_op_t *iop; u_int cr_field,cr_bit; m_uint32_t new_ia; u_char *jump_ptr; int cond,ctr; + ppc32_jit_start_hreg_seq(cpu,"bclr"); + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + + iop = ppc32_op_emit_insn_output(cpu,5,"bclr"); + /* Get the wanted value for the condition bit and CTR value */ cond = (bo >> 3) & 0x1; ctr = (bo >> 1) & 0x1; @@ -1074,15 +1590,15 @@ /* Compute the new ia */ new_ia = sign_extend_32(bd << 2,16); if (!(insn & 0x02)) - new_ia += b->start_ia + ((b->ppc_trans_pos-1) << 2); + new_ia += b->start_ia + (b->ppc_trans_pos << 2); - ppc32_load_imm(b,X86_EAX,1); + x86_mov_reg_imm(iop->ob_ptr,hreg_t0,1); /* Decrement the count register */ if (!(bo & 0x04)) { - x86_dec_membase(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr)); - x86_set_reg(b->jit_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,X86_EBX,FALSE); - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_EBX); + x86_dec_membase(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ctr)); + x86_set_reg(iop->ob_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,hreg_t1,FALSE); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } /* Test the condition bit */ @@ -1090,31 +1606,39 @@ cr_field = ppc32_get_cr_field(bi); cr_bit = ppc32_get_cr_bit(bi); - x86_test_membase_imm(b->jit_ptr, + ppc32_op_emit_require_flags(cpu,cr_field); + + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(cr_field), (1 << cr_bit)); - x86_set_reg(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,X86_ECX,FALSE); - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EAX,X86_ECX); + x86_set_reg(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,hreg_t1,FALSE); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } /* Set the return address */ - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,OFFSET(cpu_ppc_t,lr),4); + x86_mov_reg_membase(iop->ob_ptr,hreg_t1,X86_EDI,OFFSET(cpu_ppc_t,lr),4); - if (insn & 1) - ppc32_set_lr(b,b->start_ia + (b->ppc_trans_pos << 2)); + if (insn & 1) { + ppc32_set_lr(iop,b->start_ia + ((b->ppc_trans_pos+1) << 2)); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1)<<2)); + } /* Branching */ - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x01); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); + + jump_ptr = iop->ob_ptr; + x86_branch32(iop->ob_ptr,X86_CC_Z,0,FALSE); + + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t1,0xFFFFFFFC); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),hreg_t1,4); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); - jump_ptr = b->jit_ptr; - x86_branch32(b->jit_ptr,X86_CC_Z,0,FALSE); + x86_patch(jump_ptr,iop->ob_ptr); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EDX,0xFFFFFFFC); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,ia),X86_EDX,4); - ppc32_jit_tcb_push_epilog(b); + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); - x86_patch(jump_ptr,b->jit_ptr); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1124,10 +1648,22 @@ int rd = bits(insn,23,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_ra,hreg_rb; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"cmp"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"cmp"); - ppc32_load_gpr(b,X86_EBX,ra); - ppc32_alu_gpr(b,X86_CMP,X86_EBX,rb); - ppc32_update_cr(b,rd,TRUE); + x86_alu_reg_reg(iop->ob_ptr,X86_CMP,hreg_ra,hreg_rb); + ppc32_op_emit_update_flags(cpu,rd,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1138,12 +1674,19 @@ int ra = bits(insn,16,20); m_uint16_t imm = bits(insn,0,15); m_uint32_t tmp = sign_extend_32(imm,16); + int hreg_ra; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"cmpi"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); - ppc32_load_imm(b,X86_EBX,tmp); - ppc32_load_gpr(b,X86_ESI,ra); - x86_alu_reg_reg(b->jit_ptr,X86_CMP,X86_ESI,X86_EBX); + iop = ppc32_op_emit_insn_output(cpu,1,"cmpi"); - ppc32_update_cr(b,rd,TRUE); + x86_alu_reg_imm(iop->ob_ptr,X86_CMP,hreg_ra,tmp); + ppc32_op_emit_update_flags(cpu,rd,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1153,10 +1696,22 @@ int rd = bits(insn,23,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_ra,hreg_rb; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"cmpl"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"cmpl"); - ppc32_load_gpr(b,X86_EAX,ra); - ppc32_alu_gpr(b,X86_CMP,X86_EAX,rb); - ppc32_update_cr(b,rd,FALSE); + x86_alu_reg_reg(iop->ob_ptr,X86_CMP,hreg_ra,hreg_rb); + ppc32_op_emit_update_flags(cpu,rd,FALSE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1165,13 +1720,20 @@ { int rd = bits(insn,23,25); int ra = bits(insn,16,20); - m_uint16_t imm = bits(insn,0,15); + m_uint32_t imm = bits(insn,0,15); + int hreg_ra; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"cmpli"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); - ppc32_load_imm(b,X86_EBX,imm); - ppc32_load_gpr(b,X86_ESI,ra); - x86_alu_reg_reg(b->jit_ptr,X86_CMP,X86_ESI,X86_EBX); + iop = ppc32_op_emit_insn_output(cpu,1,"cmpli"); - ppc32_update_cr(b,rd,FALSE); + x86_alu_reg_imm(iop->ob_ptr,X86_CMP,hreg_ra,imm); + ppc32_op_emit_update_flags(cpu,rd,FALSE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1181,32 +1743,48 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"crand"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"crand"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of AND between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EBX,X86_EAX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,X86_EDX); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1216,32 +1794,48 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"crandc"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"crandc"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_Z,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_Z,hreg_t0,FALSE); /* result of AND between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EBX,X86_EAX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,X86_EDX); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1251,33 +1845,49 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"creqv"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"creqv"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of XOR between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EAX); - x86_not_reg(b->jit_ptr,X86_EBX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,X86_EDX); + x86_not_reg(iop->ob_ptr,hreg_t0); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1287,33 +1897,49 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"crnand"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"crnand"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of NAND between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_EBX,X86_EAX); - x86_not_reg(b->jit_ptr,X86_EBX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,X86_EDX); + x86_not_reg(iop->ob_ptr,hreg_t0); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1323,33 +1949,49 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"crnor"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"crnor"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of NOR between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); - x86_not_reg(b->jit_ptr,X86_EBX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,X86_EDX); + x86_not_reg(iop->ob_ptr,hreg_t0); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1359,32 +2001,48 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"cror"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"cror"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of OR between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,X86_EDX); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1394,32 +2052,48 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"crorc"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"crorc"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_Z,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_Z,hreg_t0,FALSE); /* result of ORC between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,X86_EDX); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1429,32 +2103,48 @@ int bd = bits(insn,21,25); int bb = bits(insn,16,20); int ba = bits(insn,11,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_start_hreg_seq(cpu,"crxor"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(ba)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bb)); + ppc32_op_emit_require_flags(cpu,ppc32_get_cr_field(bd)); + + iop = ppc32_op_emit_insn_output(cpu,3,"crxor"); /* test $ba bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EAX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,X86_EDX,FALSE); /* test $bb bit */ - x86_test_membase_imm(b->jit_ptr, + x86_test_membase_imm(iop->ob_ptr, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_EBX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of XOR between $ba and $bb */ - x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EAX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,0x01); + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,X86_EDX); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - x86_alu_membase_imm(b->jit_ptr,X86_AND, + x86_alu_membase_imm(iop->ob_ptr,X86_AND, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd))); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,ppc32_get_cr_bit(bd)); - x86_alu_membase_reg(b->jit_ptr,X86_OR, + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + x86_alu_membase_reg(iop->ob_ptr,X86_OR, X86_EDI,PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - X86_EBX); + hreg_t0); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1464,19 +2154,36 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rb; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EAX,ra); - ppc32_load_gpr(b,X86_EBX,rb); - ppc32_load_imm(b,X86_EDX,0); + ppc32_jit_start_hreg_seq(cpu,"divwu"); + ppc32_jit_alloc_hreg_forced(cpu,X86_EAX); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + /* $rd = $ra / $rb */ + ppc32_op_emit_load_gpr(cpu,X86_EAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); - x86_div_reg(b->jit_ptr,X86_EBX,0); - ppc32_store_gpr(b,rd,X86_EAX); + iop = ppc32_op_emit_insn_output(cpu,2,"divwu"); + ppc32_load_imm(&iop->ob_ptr,X86_EDX,0); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); - ppc32_update_cr0(b); - } - + x86_div_reg(iop->ob_ptr,hreg_rb,0); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); + + ppc32_op_emit_store_gpr(cpu,rd,X86_EAX); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + /* edx:eax are directly modified: throw them */ + ppc32_op_emit_alter_host_reg(cpu,X86_EAX); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1486,18 +2193,40 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb; + jit_op_t *iop; /* $ra = ~($rs ^ $rb) */ - ppc32_load_gpr(b,X86_EBX,rs); - ppc32_alu_gpr(b,X86_XOR,X86_EBX,rb); - x86_not_reg(b->jit_ptr,X86_EBX); - ppc32_store_gpr(b,ra,X86_EBX); - - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); + ppc32_jit_start_hreg_seq(cpu,"eqv"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"eqv"); + + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb); + else if (ra == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rs); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb); } + x86_not_reg(iop->ob_ptr,hreg_ra); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1506,17 +2235,33 @@ { int rs = bits(insn,21,25); int ra = bits(insn,16,20); + int hreg_rs,hreg_ra; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EBX,rs); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,24); - x86_shift_reg_imm(b->jit_ptr,X86_SAR,X86_EBX,24); - ppc32_store_gpr(b,ra,X86_EBX); + /* $ra = extsb($rs) */ + ppc32_jit_start_hreg_seq(cpu,"extsb"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,2,"extsb"); + + if (rs != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_ra,24); + x86_shift_reg_imm(iop->ob_ptr,X86_SAR,hreg_ra,24); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1525,17 +2270,33 @@ { int rs = bits(insn,21,25); int ra = bits(insn,16,20); + int hreg_rs,hreg_ra; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EBX,rs); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EBX,16); - x86_shift_reg_imm(b->jit_ptr,X86_SAR,X86_EBX,16); - ppc32_store_gpr(b,ra,X86_EBX); + /* $ra = extsh($rs) */ + ppc32_jit_start_hreg_seq(cpu,"extsh"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,2,"extsh"); + + if (rs != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_ra,16); + x86_shift_reg_imm(iop->ob_ptr,X86_SAR,hreg_ra,16); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1546,8 +2307,9 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - //ppc32_emit_memop(b,PPC_MEMOP_LBZ,ra,offset,rs,0); - ppc32_emit_memop_fast(b,0,PPC_MEMOP_LBZ,ra,offset,rs,ppc32_memop_fast_lbz); + //ppc32_emit_memop(cpu,b,PPC_MEMOP_LBZ,ra,offset,rs,0); + ppc32_emit_memop_fast(cpu,b,0,PPC_MEMOP_LBZ,ra,offset,rs, + ppc32_memop_fast_lbz); return(0); } @@ -1558,7 +2320,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_LBZ,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_LBZ,ra,offset,rs,1); return(0); } @@ -1569,7 +2331,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LBZ,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LBZ,ra,rb,rs,1); return(0); } @@ -1580,7 +2342,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LBZ,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LBZ,ra,rb,rs,0); return(0); } @@ -1591,7 +2353,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_LHA,ra,offset,rs,0); + ppc32_emit_memop(cpu,b,PPC_MEMOP_LHA,ra,offset,rs,0); return(0); } @@ -1602,7 +2364,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_LHA,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_LHA,ra,offset,rs,1); return(0); } @@ -1613,7 +2375,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LHA,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHA,ra,rb,rs,1); return(0); } @@ -1624,7 +2386,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LHA,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHA,ra,rb,rs,0); return(0); } @@ -1635,7 +2397,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_LHZ,ra,offset,rs,0); + ppc32_emit_memop(cpu,b,PPC_MEMOP_LHZ,ra,offset,rs,0); return(0); } @@ -1646,7 +2408,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_LHZ,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_LHZ,ra,offset,rs,1); return(0); } @@ -1657,7 +2419,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LHZ,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHZ,ra,rb,rs,1); return(0); } @@ -1668,7 +2430,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LHZ,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LHZ,ra,rb,rs,0); return(0); } @@ -1680,7 +2442,8 @@ m_uint16_t offset = bits(insn,0,15); //ppc32_emit_memop(b,PPC_MEMOP_LWZ,ra,offset,rs,0); - ppc32_emit_memop_fast(b,0,PPC_MEMOP_LWZ,ra,offset,rs,ppc32_memop_fast_lwz); + ppc32_emit_memop_fast(cpu,b,0,PPC_MEMOP_LWZ,ra,offset,rs, + ppc32_memop_fast_lwz); return(0); } @@ -1691,7 +2454,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_LWZ,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_LWZ,ra,offset,rs,1); return(0); } @@ -1702,7 +2465,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LWZ,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LWZ,ra,rb,rs,1); return(0); } @@ -1713,7 +2476,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_LWZ,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_LWZ,ra,rb,rs,0); return(0); } @@ -1722,12 +2485,24 @@ { int rd = bits(insn,23,25); int rs = bits(insn,18,20); + int hreg_t0; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"mcrf"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_op_emit_require_flags(cpu,rs); + + iop = ppc32_op_emit_insn_output(cpu,1,"mcrf"); /* Load "rs" field in %edx */ - x86_mov_reg_membase(b->jit_ptr,X86_EDX,X86_EDI,PPC32_CR_FIELD_OFFSET(rs),4); + x86_mov_reg_membase(iop->ob_ptr,hreg_t0, + X86_EDI,PPC32_CR_FIELD_OFFSET(rs),4); /* Store it in "rd" field */ - x86_mov_membase_reg(b->jit_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(rd),X86_EDX,4); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(rd), + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1735,19 +2510,30 @@ DECLARE_INSN(MFCR) { int rd = bits(insn,21,25); + int hreg_rd,hreg_t0; + jit_op_t *iop; int i; - x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EAX,X86_EAX); + ppc32_jit_start_hreg_seq(cpu,"mfcr"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_op_emit_require_flags(cpu,JIT_OP_PPC_ALL_FLAGS); + + iop = ppc32_op_emit_insn_output(cpu,3,"mfcr"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_rd,hreg_rd); for(i=0;i<8;i++) { /* load field in %edx */ - x86_mov_reg_membase(b->jit_ptr,X86_EDX, + x86_mov_reg_membase(iop->ob_ptr,hreg_t0, X86_EDI,PPC32_CR_FIELD_OFFSET(i),4); - x86_shift_reg_imm(b->jit_ptr,X86_SHL,X86_EAX,4); - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_EDX); + x86_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_rd,4); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_rd,hreg_t0); } - ppc32_store_gpr(b,rd,X86_EAX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1755,9 +2541,17 @@ DECLARE_INSN(MFMSR) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; - x86_mov_reg_membase(b->jit_ptr,X86_EAX,X86_EDI,OFFSET(cpu_ppc_t,msr),4); - ppc32_store_gpr(b,rd,X86_EAX); + ppc32_jit_start_hreg_seq(cpu,"mfmsr"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + + iop = ppc32_op_emit_insn_output(cpu,1,"mfmsr"); + x86_mov_reg_membase(iop->ob_ptr,hreg_rd,X86_EDI,OFFSET(cpu_ppc_t,msr),4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1766,10 +2560,19 @@ { int rd = bits(insn,21,25); int sr = bits(insn,16,19); + int hreg_rd; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"mfsr"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - x86_mov_reg_membase(b->jit_ptr,X86_EAX, + iop = ppc32_op_emit_insn_output(cpu,1,"mfsr"); + + x86_mov_reg_membase(iop->ob_ptr,hreg_rd, X86_EDI,(OFFSET(cpu_ppc_t,sr) + (sr << 2)),4); - ppc32_store_gpr(b,rd,X86_EAX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1778,22 +2581,33 @@ { int rs = bits(insn,21,25); int crm = bits(insn,12,19); + int hreg_rs,hreg_t0; + jit_op_t *iop; int i; - ppc32_load_gpr(b,X86_EDX,rs); + ppc32_jit_start_hreg_seq(cpu,"mtcrf"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,3,"mtcrf"); for(i=0;i<8;i++) if (crm & (1 << (7 - i))) { - x86_mov_reg_reg(b->jit_ptr,X86_EAX,X86_EDX,4); + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); if (i != 7) - x86_shift_reg_imm(b->jit_ptr,X86_SHR,X86_EAX,28 - (i << 2)); + x86_shift_reg_imm(iop->ob_ptr,X86_SHR,hreg_t0,28 - (i << 2)); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x0F); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(i), - X86_EAX,4); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x0F); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,PPC32_CR_FIELD_OFFSET(i), + hreg_t0,4); } + ppc32_op_emit_basic_opcode(cpu,JIT_OP_TRASH_FLAGS); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1803,17 +2617,34 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rb; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EAX,ra); - ppc32_load_gpr(b,X86_EBX,rb); - x86_mul_reg(b->jit_ptr,X86_EBX,1); - ppc32_store_gpr(b,rd,X86_EDX); + ppc32_jit_start_hreg_seq(cpu,"mulhw"); + ppc32_jit_alloc_hreg_forced(cpu,X86_EAX); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,X86_EAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + /* rd = hi(ra * rb) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mulhw"); + x86_mul_reg(iop->ob_ptr,hreg_rb,1); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX); - ppc32_update_cr0(b); - } + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX); + + ppc32_op_emit_store_gpr(cpu,rd,X86_EDX); + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + /* edx:eax are directly modified: throw them */ + ppc32_op_emit_alter_host_reg(cpu,X86_EAX); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1823,17 +2654,34 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rb; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EAX,ra); - ppc32_load_gpr(b,X86_EBX,rb); - x86_mul_reg(b->jit_ptr,X86_EBX,0); - ppc32_store_gpr(b,rd,X86_EDX); + ppc32_jit_start_hreg_seq(cpu,"mulhwu"); + ppc32_jit_alloc_hreg_forced(cpu,X86_EAX); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,X86_EAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + /* rd = hi(ra * rb) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mulhwu"); + x86_mul_reg(iop->ob_ptr,hreg_rb,0); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EDX,X86_EDX); - ppc32_update_cr0(b); - } + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,X86_EDX,X86_EDX); + ppc32_op_emit_store_gpr(cpu,rd,X86_EDX); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + /* edx:eax are directly modified: throw them */ + ppc32_op_emit_alter_host_reg(cpu,X86_EAX); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1843,12 +2691,28 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); m_uint32_t imm = bits(insn,0,15); + int hreg_t0; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"mulli"); + ppc32_jit_alloc_hreg_forced(cpu,X86_EAX); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_load_gpr(cpu,X86_EAX,ra); - ppc32_load_gpr(b,X86_EAX,ra); - ppc32_load_imm(b,X86_EBX,sign_extend_32(imm,16)); + /* rd = lo(ra * imm) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mulli"); - x86_mul_reg(b->jit_ptr,X86_EBX,1); - ppc32_store_gpr(b,rd,X86_EAX); + ppc32_load_imm(&iop->ob_ptr,hreg_t0,sign_extend_32(imm,16)); + x86_mul_reg(iop->ob_ptr,hreg_t0,1); + ppc32_op_emit_store_gpr(cpu,rd,X86_EAX); + + /* edx:eax are directly modified: throw them */ + ppc32_op_emit_alter_host_reg(cpu,X86_EAX); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1858,17 +2722,34 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rb; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EAX,ra); - ppc32_load_gpr(b,X86_EBX,rb); - x86_mul_reg(b->jit_ptr,X86_EBX,1); - ppc32_store_gpr(b,rd,X86_EAX); + ppc32_jit_start_hreg_seq(cpu,"mullw"); + ppc32_jit_alloc_hreg_forced(cpu,X86_EAX); + ppc32_jit_alloc_hreg_forced(cpu,X86_EDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,X86_EAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + /* rd = lo(ra * rb) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mullw"); + x86_mul_reg(iop->ob_ptr,hreg_rb,1); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EAX,X86_EAX); - ppc32_update_cr0(b); - } + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,X86_EAX,X86_EAX); + + ppc32_op_emit_store_gpr(cpu,rd,X86_EAX); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + /* edx:eax are directly modified: throw them */ + ppc32_op_emit_alter_host_reg(cpu,X86_EAX); + ppc32_op_emit_alter_host_reg(cpu,X86_EDX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1878,18 +2759,40 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb; + jit_op_t *iop; /* $ra = ~($rs & $rb) */ - ppc32_load_gpr(b,X86_EBX,rs); - ppc32_alu_gpr(b,X86_AND,X86_EBX,rb); - x86_not_reg(b->jit_ptr,X86_EBX); - ppc32_store_gpr(b,ra,X86_EBX); - - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); + ppc32_jit_start_hreg_seq(cpu,"nand"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"nand"); + + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb); + else if (ra == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rs); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb); } + x86_not_reg(iop->ob_ptr,hreg_ra); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1898,16 +2801,32 @@ { int rd = bits(insn,21,25); int ra = bits(insn,16,20); + int hreg_rd,hreg_ra; + jit_op_t *iop; - ppc32_load_gpr(b,X86_EBX,ra); - x86_neg_reg(b->jit_ptr,X86_EBX); - ppc32_store_gpr(b,rd,X86_EBX); + /* $rd = neg($ra) */ + ppc32_jit_start_hreg_seq(cpu,"neg"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + + iop = ppc32_op_emit_insn_output(cpu,1,"neg"); + + if (rd != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + x86_neg_reg(iop->ob_ptr,hreg_rd); + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd); + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1917,18 +2836,40 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb; + jit_op_t *iop; /* $ra = ~($rs | $rb) */ - ppc32_load_gpr(b,X86_EBX,rs); - ppc32_alu_gpr(b,X86_OR,X86_EBX,rb); - x86_not_reg(b->jit_ptr,X86_EBX); - ppc32_store_gpr(b,ra,X86_EBX); - - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); + ppc32_jit_start_hreg_seq(cpu,"nor"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"nor"); + + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb); + else if (ra == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rs); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb); } + x86_not_reg(iop->ob_ptr,hreg_ra); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1938,20 +2879,55 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb; + jit_op_t *iop; - ppc32_load_gpr(b,X86_ECX,rs); + /* $ra = $rs | $rb */ + ppc32_jit_start_hreg_seq(cpu,"or"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); - if (rs != rb) - ppc32_alu_gpr(b,X86_OR,X86_ECX,rb); + /* special optimization for move/nop operation */ + if (rs == rb) { + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + iop = ppc32_op_emit_insn_output(cpu,2,"or"); - ppc32_store_gpr(b,ra,X86_ECX); + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); - if (insn & 1) { - if (rs == rb) - x86_test_reg_reg(b->jit_ptr,X86_ECX,X86_ECX); - ppc32_update_cr0(b); + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); + return(0); } + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"or"); + + if (ra == rs) { + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb); + } else if (ra == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rs); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb); + } + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1961,16 +2937,39 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb,hreg_t0; + jit_op_t *iop; - /* $ra = $rs | ~$rb */ - ppc32_load_gpr(b,X86_EBX,rb); - x86_not_reg(b->jit_ptr,X86_EBX); - ppc32_alu_gpr(b,X86_OR,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + /* $ra = $rs & ~$rb */ + ppc32_jit_start_hreg_seq(cpu,"orc"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"orc"); + + /* $t0 = ~$rb */ + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4); + x86_not_reg(iop->ob_ptr,hreg_t0); + + /* $ra = $rs | $t0 */ + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_t0); + else { + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,hreg_rs); + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); + } + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); if (insn & 1) - ppc32_update_cr0(b); + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1980,11 +2979,26 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); m_uint16_t imm = bits(insn,0,15); + m_uint32_t tmp = imm; + int hreg_rs,hreg_ra; + jit_op_t *iop; /* $ra = $rs | imm */ - ppc32_load_imm(b,X86_EBX,imm); - ppc32_alu_gpr(b,X86_OR,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"ori"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,1,"ori"); + + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_OR,hreg_ra,tmp); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1993,12 +3007,27 @@ { int rs = bits(insn,21,25); int ra = bits(insn,16,20); - m_uint32_t imm = bits(insn,0,15); + m_uint16_t imm = bits(insn,0,15); + m_uint32_t tmp = imm << 16; + int hreg_rs,hreg_ra; + jit_op_t *iop; + + /* $ra = $rs | imm */ + ppc32_jit_start_hreg_seq(cpu,"oris"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,1,"oris"); + + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_OR,hreg_ra,tmp); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); - /* $ra = $rs | (imm << 16) */ - ppc32_load_imm(b,X86_EBX,imm << 16); - ppc32_alu_gpr(b,X86_OR,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2011,30 +3040,42 @@ int mb = bits(insn,6,10); int me = bits(insn,1,5); register m_uint32_t mask; - + int hreg_rs,hreg_ra,hreg_t0; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"rlwimi"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + mask = ppc32_rotate_mask(mb,me); - /* Apply inverse mask to %eax "ra" */ - ppc32_load_gpr(b,X86_EAX,ra); + iop = ppc32_op_emit_insn_output(cpu,2,"rlwimi"); + + /* Apply inverse mask to $ra */ if (mask != 0) - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,~mask); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,~mask); - /* Rotate %ebx ("rs") of "sh" bits and apply the mask */ - ppc32_load_gpr(b,X86_EBX,rs); + /* Rotate $rs of "sh" bits and apply the mask */ + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); if (sh != 0) - x86_shift_reg_imm(b->jit_ptr,X86_ROL,X86_EBX,sh); + x86_shift_reg_imm(iop->ob_ptr,X86_ROL,hreg_t0,sh); if (mask != 0xFFFFFFFF) - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,mask); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask); /* Store the result */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EBX,X86_EAX); - ppc32_store_gpr(b,ra,X86_EBX); + x86_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_ra,hreg_t0); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); if (insn & 1) - ppc32_update_cr0(b); + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2047,25 +3088,38 @@ int mb = bits(insn,6,10); int me = bits(insn,1,5); register m_uint32_t mask; + int hreg_rs,hreg_ra; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"rlwinm"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + iop = ppc32_op_emit_insn_output(cpu,2,"rlwinm"); + + /* Rotate $rs of "sh" bits and apply the mask */ mask = ppc32_rotate_mask(mb,me); - /* Rotate %ebx ("rs") of "sh" bits and apply the mask */ - ppc32_load_gpr(b,X86_EBX,rs); + if (rs != ra) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); if (sh != 0) - x86_shift_reg_imm(b->jit_ptr,X86_ROL,X86_EBX,sh); + x86_shift_reg_imm(iop->ob_ptr,X86_ROL,hreg_ra,sh); if (mask != 0xFFFFFFFF) - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,mask); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,mask); - ppc32_store_gpr(b,ra,X86_EBX); + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2078,26 +3132,47 @@ int mb = bits(insn,6,10); int me = bits(insn,1,5); register m_uint32_t mask; + int hreg_rs,hreg_ra,hreg_t0; + jit_op_t *iop; - mask = ppc32_rotate_mask(mb,me); + /* ecx is directly modified: throw it */ + ppc32_op_emit_alter_host_reg(cpu,X86_ECX); + + ppc32_jit_start_hreg_seq(cpu,"rlwnm"); + ppc32_jit_alloc_hreg_forced(cpu,X86_ECX); + + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,X86_ECX,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"rlwnm"); /* Load the shift register ("sh") */ - ppc32_load_gpr(b,X86_ECX,rb); + mask = ppc32_rotate_mask(mb,me); - /* Rotate %ebx ("rs") and apply the mask */ - ppc32_load_gpr(b,X86_EBX,rs); - x86_shift_reg(b->jit_ptr,X86_ROL,X86_EBX); + /* Rotate $rs and apply the mask */ + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); + + x86_shift_reg(iop->ob_ptr,X86_ROL,hreg_t0); if (mask != 0xFFFFFFFF) - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EBX,mask); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask); - ppc32_store_gpr(b,ra,X86_EBX); + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2108,27 +3183,45 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); u_char *test1; + int hreg_rs,hreg_ra,hreg_t0; + jit_op_t *iop; - /* If count >= 32, then null result */ - ppc32_load_gpr(b,X86_ECX,rb); - x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EBX); - - x86_test_reg_imm(b->jit_ptr,X86_ECX,0x20); - test1 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); + /* ecx is directly modified: throw it */ + ppc32_op_emit_alter_host_reg(cpu,X86_ECX); - ppc32_load_gpr(b,X86_EBX,rs); - x86_shift_reg(b->jit_ptr,X86_SHL,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"slw"); + ppc32_jit_alloc_hreg_forced(cpu,X86_ECX); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + /* $ra = $rs << $rb. If count >= 32, then null result */ + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,X86_ECX,rb); + + iop = ppc32_op_emit_insn_output(cpu,3,"slw"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0); + x86_test_reg_imm(iop->ob_ptr,X86_ECX,0x20); + test1 = iop->ob_ptr; + x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); + + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); + x86_shift_reg(iop->ob_ptr,X86_SHL,hreg_t0); + + /* store the result */ + x86_patch(test1,iop->ob_ptr); + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); - /* Store the result */ - x86_patch(test1,b->jit_ptr); - ppc32_store_gpr(b,ra,X86_EBX); + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2139,31 +3232,42 @@ int ra = bits(insn,16,20); int sh = bits(insn,11,15); register m_uint32_t mask; + int hreg_rs,hreg_ra,hreg_t0; + jit_op_t *iop; - mask = ~(0xFFFFFFFFU << sh); + ppc32_jit_start_hreg_seq(cpu,"srawi"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); /* $ra = (int32)$rs >> sh */ - ppc32_load_gpr(b,X86_EBX,rs); - x86_mov_reg_reg(b->jit_ptr,X86_ESI,X86_EBX,4); - x86_shift_reg_imm(b->jit_ptr,X86_SAR,X86_EBX,sh); - ppc32_store_gpr(b,ra,X86_EBX); - - /* test the sign-bit of gpr[rs] */ - x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); - x86_set_reg(b->jit_ptr,X86_CC_LT,X86_EAX,TRUE); - - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,mask); - x86_set_reg(b->jit_ptr,X86_CC_NZ,X86_ECX,TRUE); - - x86_alu_reg_reg(b->jit_ptr,X86_AND,X86_ECX,X86_EAX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_ECX,0x1); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_ECX,4); + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } + iop = ppc32_op_emit_insn_output(cpu,3,"srawi"); + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); + + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_shift_reg_imm(iop->ob_ptr,X86_SAR,hreg_ra,sh); + + /* set XER_CA depending on the result */ + mask = ~(0xFFFFFFFFU << sh) | 0x80000000; + + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask); + x86_alu_reg_imm(iop->ob_ptr,X86_CMP,hreg_t0,0x80000000); + x86_set_reg(iop->ob_ptr,X86_CC_A,hreg_t0,FALSE); + x86_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x1); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t0,4); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2174,27 +3278,45 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); u_char *test1; + int hreg_rs,hreg_ra,hreg_t0; + jit_op_t *iop; - /* If count >= 32, then null result */ - ppc32_load_gpr(b,X86_ECX,rb); - x86_alu_reg_reg(b->jit_ptr,X86_XOR,X86_EBX,X86_EBX); - - x86_test_reg_imm(b->jit_ptr,X86_ECX,0x20); - test1 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); + /* ecx is directly modified: throw it */ + ppc32_op_emit_alter_host_reg(cpu,X86_ECX); - ppc32_load_gpr(b,X86_EBX,rs); - x86_shift_reg(b->jit_ptr,X86_SHR,X86_EBX); + ppc32_jit_start_hreg_seq(cpu,"srw"); + ppc32_jit_alloc_hreg_forced(cpu,X86_ECX); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + /* $ra = $rs >> $rb. If count >= 32, then null result */ + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,X86_ECX,rb); + + iop = ppc32_op_emit_insn_output(cpu,3,"srw"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0); + x86_test_reg_imm(iop->ob_ptr,X86_ECX,0x20); + test1 = iop->ob_ptr; + x86_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); + + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); + x86_shift_reg(iop->ob_ptr,X86_SHR,hreg_t0); + + /* store the result */ + x86_patch(test1,iop->ob_ptr); + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); - /* Store the result */ - x86_patch(test1,b->jit_ptr); - ppc32_store_gpr(b,ra,X86_EBX); + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_ra,hreg_ra); - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_EBX,X86_EBX); - ppc32_update_cr0(b); - } - + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2206,7 +3328,8 @@ m_uint16_t offset = bits(insn,0,15); //ppc32_emit_memop(b,PPC_MEMOP_STB,ra,offset,rs,0); - ppc32_emit_memop_fast(b,1,PPC_MEMOP_STB,ra,offset,rs,ppc32_memop_fast_stb); + ppc32_emit_memop_fast(cpu,b,1,PPC_MEMOP_STB,ra,offset,rs, + ppc32_memop_fast_stb); return(0); } @@ -2217,7 +3340,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_STB,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_STB,ra,offset,rs,1); return(0); } @@ -2228,7 +3351,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_STB,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STB,ra,rb,rs,1); return(0); } @@ -2239,7 +3362,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_STB,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STB,ra,rb,rs,0); return(0); } @@ -2250,7 +3373,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_STH,ra,offset,rs,0); + ppc32_emit_memop(cpu,b,PPC_MEMOP_STH,ra,offset,rs,0); return(0); } @@ -2261,7 +3384,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_STH,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_STH,ra,offset,rs,1); return(0); } @@ -2272,7 +3395,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_STH,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STH,ra,rb,rs,1); return(0); } @@ -2283,7 +3406,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_STH,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STH,ra,rb,rs,0); return(0); } @@ -2295,7 +3418,8 @@ m_uint16_t offset = bits(insn,0,15); //ppc32_emit_memop(b,PPC_MEMOP_STW,ra,offset,rs,0); - ppc32_emit_memop_fast(b,1,PPC_MEMOP_STW,ra,offset,rs,ppc32_memop_fast_stw); + ppc32_emit_memop_fast(cpu,b,1,PPC_MEMOP_STW,ra,offset,rs, + ppc32_memop_fast_stw); return(0); } @@ -2306,7 +3430,7 @@ int ra = bits(insn,16,20); m_uint16_t offset = bits(insn,0,15); - ppc32_emit_memop(b,PPC_MEMOP_STW,ra,offset,rs,1); + ppc32_emit_memop(cpu,b,PPC_MEMOP_STW,ra,offset,rs,1); return(0); } @@ -2317,7 +3441,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_STW,ra,rb,rs,1); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STW,ra,rb,rs,1); return(0); } @@ -2328,7 +3452,7 @@ int ra = bits(insn,16,20); int rb = bits(insn,11,15); - ppc32_emit_memop_idx(b,PPC_MEMOP_STW,ra,rb,rs,0); + ppc32_emit_memop_idx(cpu,b,PPC_MEMOP_STW,ra,rb,rs,0); return(0); } @@ -2338,15 +3462,39 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rd,hreg_ra,hreg_rb,hreg_t0; + jit_op_t *iop; + + /* $rd = $rb - $ra */ + ppc32_jit_start_hreg_seq(cpu,"subf"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"subf"); + + if (rd == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_SUB,hreg_rd,hreg_ra); + else if (rd == ra) { + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4); + x86_alu_reg_reg(iop->ob_ptr,X86_SUB,hreg_t0,hreg_ra); + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); + } else { + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_rb,4); + x86_alu_reg_reg(iop->ob_ptr,X86_SUB,hreg_rd,hreg_ra); + } - /* $rd = $rb - $rb */ - ppc32_load_gpr(b,X86_EBX,rb); - ppc32_alu_gpr(b,X86_SUB,X86_EBX,ra); - ppc32_store_gpr(b,rd,X86_EBX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); if (insn & 1) - ppc32_update_cr0(b); - + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2356,31 +3504,51 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_ra,hreg_rb,hreg_rd,hreg_t0,hreg_t1; + jit_op_t *iop; - /* ~$ra + 1 */ - ppc32_load_gpr(b,X86_ESI,ra); - x86_not_reg(b->jit_ptr,X86_ESI); - x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESI,1); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); - - /* add $rb */ - ppc32_alu_gpr(b,X86_ADD,X86_ESI,rb); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); + /* $rd = ~$ra + 1 + $rb */ + ppc32_jit_start_hreg_seq(cpu,"subfc"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,3,"subfc"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + + /* $t0 = ~$ra + 1 */ + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + x86_not_reg(iop->ob_ptr,hreg_t0); + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_t0,1); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4); + + /* $t0 += $rb */ + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1); - ppc32_store_gpr(b,rd,X86_ESI); + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); - /* store the carry flag */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); /* update cr0 */ - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); + if (insn & 1) ppc32_update_cr0(b); - } + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2390,31 +3558,53 @@ int rd = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_ra,hreg_rb,hreg_rd,hreg_t0,hreg_t1; + jit_op_t *iop; - /* ~$ra + carry */ - ppc32_load_gpr(b,X86_ESI,ra); - x86_not_reg(b->jit_ptr,X86_ESI); - x86_alu_reg_membase(b->jit_ptr,X86_ADD,X86_ESI, + /* $rd = ~$ra + $carry (xer_ca) + $rb */ + ppc32_jit_start_hreg_seq(cpu,"subfe"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,3,"subfe"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + + /* $t0 = ~$ra + $carry */ + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + x86_not_reg(iop->ob_ptr,hreg_t0); + x86_alu_reg_membase(iop->ob_ptr,X86_ADD,hreg_t0, X86_EDI,OFFSET(cpu_ppc_t,xer_ca)); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); - /* add $rb */ - ppc32_alu_gpr(b,X86_ADD,X86_ESI,rb); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4); - ppc32_store_gpr(b,rd,X86_ESI); + /* $t0 += $rb */ + x86_alu_reg_reg(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1); - /* store the carry flag */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); + + if (insn & 1) + x86_test_reg_reg(iop->ob_ptr,hreg_rd,hreg_rd); + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); /* update cr0 */ - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,X86_ESI,X86_ESI); + if (insn & 1) ppc32_update_cr0(b); - } + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2425,24 +3615,42 @@ int ra = bits(insn,16,20); m_uint16_t imm = bits(insn,0,15); m_uint32_t tmp = sign_extend_32(imm,16); + int hreg_ra,hreg_rd,hreg_t0,hreg_t1; + jit_op_t *iop; - /* ~$ra + 1 */ - ppc32_load_gpr(b,X86_ESI,ra); - x86_not_reg(b->jit_ptr,X86_ESI); - x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESI,1); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_EAX,FALSE); - - /* add sign-extended $immediate */ - x86_alu_reg_imm(b->jit_ptr,X86_ADD,X86_ESI,tmp); - x86_set_reg(b->jit_ptr,X86_CC_C,X86_ECX,FALSE); + /* $rd = ~$ra + 1 + sign_extend(imm,16) */ + ppc32_jit_start_hreg_seq(cpu,"subfic"); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - ppc32_store_gpr(b,rd,X86_ESI); + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); - /* store the carry flag */ - x86_alu_reg_reg(b->jit_ptr,X86_OR,X86_EAX,X86_ECX); - x86_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,0x1); + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + + iop = ppc32_op_emit_insn_output(cpu,3,"subfic"); + + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + + /* $t0 = ~$ra + 1 */ + x86_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + x86_not_reg(iop->ob_ptr,hreg_t0); + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_t0,1); + + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_mov_membase_reg(iop->ob_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),hreg_t1,4); + + /* $t0 += sign_extend(imm,16) */ + x86_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_t0,tmp); + x86_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + x86_alu_membase_reg(iop->ob_ptr,X86_OR,X86_EDI,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1); - x86_mov_membase_reg(b->jit_ptr,X86_EDI,OFFSET(cpu_ppc_t,xer_ca),X86_EAX,4); + x86_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2458,14 +3666,35 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra,hreg_rb; + jit_op_t *iop; + + /* $ra = $rs ^ $rb */ + ppc32_jit_start_hreg_seq(cpu,"xor"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + iop = ppc32_op_emit_insn_output(cpu,1,"xor"); + + if (ra == rs) + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb); + else if (ra == rb) + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rs); + else { + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + x86_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb); + } - ppc32_load_gpr(b,X86_EBX,rs); - ppc32_alu_gpr(b,X86_XOR,X86_EBX,rb); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); if (insn & 1) - ppc32_update_cr0(b); + ppc32_op_emit_update_flags(cpu,0,TRUE); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2475,10 +3704,25 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); m_uint32_t imm = bits(insn,0,15); + int hreg_rs,hreg_ra; + jit_op_t *iop; + + /* $ra = $rs ^ imm */ + ppc32_jit_start_hreg_seq(cpu,"xori"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,1,"xori"); + + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); - ppc32_load_imm(b,X86_EBX,imm); - ppc32_alu_gpr(b,X86_XOR,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + x86_alu_reg_imm(iop->ob_ptr,X86_XOR,hreg_ra,imm); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2487,11 +3731,27 @@ { int rs = bits(insn,21,25); int ra = bits(insn,16,20); - m_uint32_t imm = bits(insn,0,15); + m_uint16_t imm = bits(insn,0,15); + m_uint32_t tmp = imm << 16; + int hreg_rs,hreg_ra; + jit_op_t *iop; + + /* $ra = $rs ^ (imm << 16) */ + ppc32_jit_start_hreg_seq(cpu,"xoris"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); + + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,1,"xoris"); + + if (ra != rs) + x86_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + x86_alu_reg_imm(iop->ob_ptr,X86_XOR,hreg_ra,tmp); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); - ppc32_load_imm(b,X86_EBX,imm << 16); - ppc32_alu_gpr(b,X86_XOR,X86_EBX,rs); - ppc32_store_gpr(b,ra,X86_EBX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2512,6 +3772,7 @@ { ppc32_emit_ADDIC , 0xfc000000 , 0x30000000 }, { ppc32_emit_ADDIC_dot , 0xfc000000 , 0x34000000 }, { ppc32_emit_ADDIS , 0xfc000000 , 0x3c000000 }, + { ppc32_emit_ADDZE , 0xfc00fffe , 0x7c000194 }, { ppc32_emit_AND , 0xfc0007fe , 0x7c000038 }, { ppc32_emit_ANDC , 0xfc0007fe , 0x7c000078 }, { ppc32_emit_ANDI , 0xfc000000 , 0x70000000 },