--- upstream/dynamips-0.2.7-RC2/ppc32_amd64_trans.c 2007/10/06 16:24:54 8 +++ upstream/dynamips-0.2.7-RC3/ppc32_amd64_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_amd64_trans.h" #include "memory.h" @@ -98,80 +99,85 @@ }; /* 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 inline void ppc32_load_imm(u_char **ptr,u_int reg,m_uint32_t val) { if (val) - amd64_mov_reg_imm_size(b->jit_ptr,reg,val,4); + amd64_mov_reg_imm_size(*ptr,reg,val,4); else - amd64_alu_reg_reg_size(b->jit_ptr,X86_XOR,reg,reg,4); + amd64_alu_reg_reg_size(*ptr,X86_XOR,reg,reg,4); } /* 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) { - amd64_mov_membase_imm(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ia),new_ia,4); + amd64_mov_membase_imm(*ptr,AMD64_R15,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) { - amd64_mov_membase_imm(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,lr),new_lr,4); + amd64_mov_membase_imm(iop->ob_ptr,AMD64_R15,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 %rbx, %rdx */ + ppc32_op_emit_alter_host_reg(cpu,AMD64_RBX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RSI); + 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 %rdx */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RBX, + amd64_mov_reg_membase(iop->ob_ptr,AMD64_RBX, AMD64_R15,OFFSET(cpu_ppc_t,exec_blk_map),8); - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, + amd64_mov_reg_membase(iop->ob_ptr,AMD64_RDX, AMD64_RBX,ia_hash*sizeof(void *),8); /* no JIT block found ? */ - amd64_test_reg_reg(b->jit_ptr,AMD64_RDX,AMD64_RDX); - test1 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_Z, 0, 1); + amd64_test_reg_reg(iop->ob_ptr,AMD64_RDX,AMD64_RDX); + test1 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); /* Check block IA */ - ppc32_load_imm(b,AMD64_RAX,new_page); - amd64_alu_reg_membase_size(b->jit_ptr,X86_CMP,X86_EAX,AMD64_RDX, + ppc32_load_imm(&iop->ob_ptr,AMD64_RSI,new_page); + amd64_alu_reg_membase_size(iop->ob_ptr,X86_CMP,AMD64_RAX,AMD64_RDX, OFFSET(ppc32_jit_tcb_t,start_ia),4); - test2 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_NE, 0, 1); + test2 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_NE, 0, 1); /* Jump to the code */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RSI, + amd64_mov_reg_membase(iop->ob_ptr,AMD64_RSI, AMD64_RDX,OFFSET(ppc32_jit_tcb_t,jit_insn_ptr),8); - amd64_mov_reg_membase(b->jit_ptr,AMD64_RBX, + amd64_mov_reg_membase(iop->ob_ptr,AMD64_RBX, AMD64_RSI,ia_offset * sizeof(void *),8); - amd64_test_reg_reg(b->jit_ptr,AMD64_RBX,AMD64_RBX); - test3 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_Z, 0, 1); - amd64_jump_reg(b->jit_ptr,AMD64_RBX); + amd64_test_reg_reg(iop->ob_ptr,AMD64_RBX,AMD64_RBX); + test3 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); + amd64_jump_reg(iop->ob_ptr,AMD64_RBX); /* Returns to caller... */ - amd64_patch(test1,b->jit_ptr); - amd64_patch(test2,b->jit_ptr); - amd64_patch(test3,b->jit_ptr); + amd64_patch(test1,iop->ob_ptr); + amd64_patch(test2,iop->ob_ptr); + amd64_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; @@ -183,42 +189,53 @@ #endif if (!return_to_caller && ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr)) { - if (jump_ptr) { - amd64_jump_code(b->jit_ptr,jump_ptr); - } else { - ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); - amd64_jump32(b->jit_ptr,0); - } + ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); + amd64_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) { - amd64_mov_reg_membase(b->jit_ptr,host_reg,AMD64_R15,REG_OFFSET(ppc_reg),4); + amd64_mov_reg_membase(*ptr,host_reg,AMD64_R15,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) { - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,REG_OFFSET(ppc_reg),host_reg,4); + amd64_mov_membase_reg(*ptr,AMD64_R15,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) { - amd64_alu_reg_membase_size(b->jit_ptr,op,host_reg, + amd64_alu_reg_membase_size(*ptr,op,host_reg, AMD64_R15,REG_OFFSET(ppc_reg),4); } @@ -263,220 +280,335 @@ 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) +{ + ppc32_op_emit_alter_host_reg(cpu,AMD64_RAX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); +} + /* 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) { - amd64_mov_reg_imm(b->jit_ptr,AMD64_RCX,f); - amd64_call_reg(b->jit_ptr,AMD64_RCX); + amd64_mov_reg_imm(*ptr,AMD64_RBX,f); + amd64_call_reg(*ptr,AMD64_RBX); } /* 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); +} + +/* ======================================================================== */ + +/* Initialize register mapping */ +void ppc32_jit_init_hreg_mapping(cpu_ppc_t *cpu) +{ + int avail_hregs[] = { AMD64_RSI, AMD64_RAX, AMD64_RCX, AMD64_RDX, + AMD64_R13, AMD64_R14, AMD64_RDI, -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(AMD64_RBX); +} + +/* ======================================================================== */ +/* 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; +} + +/* 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)) + amd64_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)); /* RSI = sign-extended offset */ - ppc32_load_imm(b,AMD64_RSI,val); + ppc32_load_imm(&iop->ob_ptr,AMD64_RSI,val); /* RSI = GPR[base] + sign-extended offset */ if (update || (base != 0)) - ppc32_alu_gpr(b,X86_ADD,AMD64_RSI,base); + ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,AMD64_RSI,base); if (update) - amd64_mov_reg_reg(b->jit_ptr,AMD64_R14,AMD64_RSI,4); + amd64_mov_reg_reg(iop->ob_ptr,AMD64_R14,AMD64_RSI,4); /* RDX = target register */ - amd64_mov_reg_imm(b->jit_ptr,AMD64_RDX,target); + amd64_mov_reg_imm(iop->ob_ptr,AMD64_RDX,target); /* RDI = CPU instance pointer */ - amd64_mov_reg_reg(b->jit_ptr,AMD64_RDI,AMD64_R15,8); + amd64_mov_reg_reg(iop->ob_ptr,AMD64_RDI,AMD64_R15,8); /* Call memory function */ - amd64_call_membase(b->jit_ptr,AMD64_R15,MEMOP_OFFSET(op)); + amd64_call_membase(iop->ob_ptr,AMD64_R15,MEMOP_OFFSET(op)); /* Exception ? */ - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RAX,AMD64_RAX,4); - test1 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_Z, 0, 1); - ppc32_jit_tcb_push_epilog(b); - amd64_patch(test1,b->jit_ptr); + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RAX,AMD64_RAX,4); + test1 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); + amd64_patch(test1,iop->ob_ptr); if (update) - ppc32_store_gpr(b,base,AMD64_R14); + ppc32_store_gpr(&iop->ob_ptr,base,AMD64_R14); } /* 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)); /* RSI = $rb */ - ppc32_load_gpr(b,AMD64_RSI,rb); + ppc32_load_gpr(&iop->ob_ptr,AMD64_RSI,rb); /* RSI = GPR[base] + sign-extended offset */ if (update || (ra != 0)) - ppc32_alu_gpr(b,X86_ADD,AMD64_RSI,ra); + ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,AMD64_RSI,ra); if (update) - amd64_mov_reg_reg(b->jit_ptr,AMD64_R14,AMD64_RSI,4); + amd64_mov_reg_reg(iop->ob_ptr,AMD64_R14,AMD64_RSI,4); /* RDX = target register */ - amd64_mov_reg_imm(b->jit_ptr,AMD64_RDX,target); + amd64_mov_reg_imm(iop->ob_ptr,AMD64_RDX,target); /* RDI = CPU instance pointer */ - amd64_mov_reg_reg(b->jit_ptr,AMD64_RDI,AMD64_R15,8); + amd64_mov_reg_reg(iop->ob_ptr,AMD64_RDI,AMD64_R15,8); /* Call memory function */ - amd64_call_membase(b->jit_ptr,AMD64_R15,MEMOP_OFFSET(op)); + amd64_call_membase(iop->ob_ptr,AMD64_R15,MEMOP_OFFSET(op)); /* Exception ? */ - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RAX,AMD64_RAX,4); - test1 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_Z, 0, 1); - ppc32_jit_tcb_push_epilog(b); - amd64_patch(test1,b->jit_ptr); + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RAX,AMD64_RAX,4); + test1 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); + amd64_patch(test1,iop->ob_ptr); if (update) - ppc32_store_gpr(b,ra,AMD64_R14); + ppc32_store_gpr(&iop->ob_ptr,ra,AMD64_R14); } -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) { - amd64_clear_reg(b->jit_ptr,AMD64_RCX); - amd64_mov_reg_memindex(b->jit_ptr,AMD64_RCX,AMD64_RBX,0,AMD64_RSI,0,1); - ppc32_store_gpr(b,target,AMD64_RCX); + amd64_clear_reg(iop->ob_ptr,AMD64_RCX); + amd64_mov_reg_memindex(iop->ob_ptr,AMD64_RCX,AMD64_RBX,0,AMD64_RSI,0,1); + ppc32_store_gpr(&iop->ob_ptr,target,AMD64_RCX); } /* 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,AMD64_RDX,target); - amd64_mov_memindex_reg(b->jit_ptr,AMD64_RBX,0,AMD64_RSI,0,AMD64_RDX,1); + ppc32_load_gpr(&iop->ob_ptr,AMD64_RDX,target); + amd64_mov_memindex_reg(iop->ob_ptr,AMD64_RBX,0,AMD64_RSI,0,AMD64_RDX,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) { - amd64_mov_reg_memindex(b->jit_ptr,AMD64_RAX,AMD64_RBX,0,AMD64_RSI,0,4); - amd64_bswap32(b->jit_ptr,AMD64_RAX); - ppc32_store_gpr(b,target,AMD64_RAX); + amd64_mov_reg_memindex(iop->ob_ptr,AMD64_RAX,AMD64_RBX,0,AMD64_RSI,0,4); + amd64_bswap32(iop->ob_ptr,AMD64_RAX); + ppc32_store_gpr(&iop->ob_ptr,target,AMD64_RAX); } /* 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,AMD64_RDX,target); - amd64_bswap32(b->jit_ptr,AMD64_RDX); - amd64_mov_memindex_reg(b->jit_ptr,AMD64_RBX,0,AMD64_RSI,0,AMD64_RDX,4); + ppc32_load_gpr(&iop->ob_ptr,AMD64_RDX,target); + amd64_bswap32(iop->ob_ptr,AMD64_RDX); + amd64_mov_memindex_reg(iop->ob_ptr,AMD64_RBX,0,AMD64_RSI,0,AMD64_RDX,4); } /* Fast memory operation */ -static void ppc32_emit_memop_fast(ppc32_jit_tcb_t *b,int write_op, - int opcode,int base,int offset,int target, +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; + + /* + * Since an exception can be triggered, clear JIT state. This allows + * to use branch target tag (we can directly branch on this instruction). + */ + ppc32_op_emit_basic_opcode(cpu,JIT_OP_BRANCH_TARGET); + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + + iop = ppc32_op_emit_insn_output(cpu,5,"memop_fast"); test2 = NULL; /* RSI = GPR[base] + sign-extended offset */ - ppc32_load_imm(b,AMD64_RSI,val); + ppc32_load_imm(&iop->ob_ptr,AMD64_RSI,val); if (base != 0) - ppc32_alu_gpr(b,X86_ADD,AMD64_RSI,base); + ppc32_alu_gpr(&iop->ob_ptr,X86_ADD,AMD64_RSI,base); /* RBX = mts32_entry index */ - amd64_mov_reg_reg_size(b->jit_ptr,X86_EBX,X86_ESI,4); - amd64_shift_reg_imm_size(b->jit_ptr,X86_SHR,X86_EBX,MTS32_HASH_SHIFT,4); - amd64_alu_reg_imm_size(b->jit_ptr,X86_AND,X86_EBX,MTS32_HASH_MASK,4); + amd64_mov_reg_reg_size(iop->ob_ptr,X86_EBX,X86_ESI,4); + amd64_shift_reg_imm_size(iop->ob_ptr,X86_SHR,X86_EBX,MTS32_HASH_SHIFT,4); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_AND,X86_EBX,MTS32_HASH_MASK,4); /* RCX = mts32 entry */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RCX, + amd64_mov_reg_membase(iop->ob_ptr,AMD64_RCX, AMD64_R15, OFFSET(cpu_ppc_t,mts_cache[PPC32_MTS_DCACHE]),8); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,5); /* TO FIX */ - amd64_alu_reg_reg(b->jit_ptr,X86_ADD,AMD64_RCX,AMD64_RBX); + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,AMD64_RBX,5); /* TO FIX */ + amd64_alu_reg_reg(iop->ob_ptr,X86_ADD,AMD64_RCX,AMD64_RBX); /* Compare virtual page address (EAX = vpage) */ - amd64_mov_reg_reg(b->jit_ptr,X86_EAX,X86_ESI,4); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,X86_EAX,PPC32_MIN_PAGE_MASK); + amd64_mov_reg_reg(iop->ob_ptr,X86_EAX,X86_ESI,4); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,X86_EAX,PPC32_MIN_PAGE_MASK); - amd64_alu_reg_membase_size(b->jit_ptr,X86_CMP,X86_EAX,AMD64_RCX, + amd64_alu_reg_membase_size(iop->ob_ptr,X86_CMP,X86_EAX,AMD64_RCX, OFFSET(mts32_entry_t,gvpa),4); - test1 = b->jit_ptr; - x86_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); + test1 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); /* Test if we are writing to a COW page */ if (write_op) { - amd64_test_membase_imm_size(b->jit_ptr, + amd64_test_membase_imm_size(iop->ob_ptr, AMD64_RCX,OFFSET(mts32_entry_t,flags), MTS_FLAG_COW|MTS_FLAG_EXEC,4); - test2 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_NZ, 0, 1); + test2 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_NZ, 0, 1); } /* ESI = offset in page, RBX = Host Page Address */ - amd64_alu_reg_imm(b->jit_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_IMASK); - amd64_mov_reg_membase(b->jit_ptr,AMD64_RBX, + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,X86_ESI,PPC32_MIN_PAGE_IMASK); + amd64_mov_reg_membase(iop->ob_ptr,AMD64_RBX, AMD64_RCX,OFFSET(mts32_entry_t,hpa),8); /* Memory access */ - op_handler(b,target); + op_handler(iop,target); - p_exit = b->jit_ptr; - amd64_jump8(b->jit_ptr,0); + p_exit = iop->ob_ptr; + amd64_jump8(iop->ob_ptr,0); /* === Slow lookup === */ - amd64_patch(test1,b->jit_ptr); + amd64_patch(test1,iop->ob_ptr); if (test2) - amd64_patch(test2,b->jit_ptr); + amd64_patch(test2,iop->ob_ptr); /* Save IA 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)); /* RDX = target register */ - amd64_mov_reg_imm(b->jit_ptr,AMD64_RDX,target); + amd64_mov_reg_imm(iop->ob_ptr,AMD64_RDX,target); /* RDI = CPU instance */ - amd64_mov_reg_reg(b->jit_ptr,AMD64_RDI,AMD64_R15,8); + amd64_mov_reg_reg(iop->ob_ptr,AMD64_RDI,AMD64_R15,8); /* Call memory access function */ - amd64_call_membase(b->jit_ptr,AMD64_R15,MEMOP_OFFSET(opcode)); + amd64_call_membase(iop->ob_ptr,AMD64_R15,MEMOP_OFFSET(opcode)); /* Exception ? */ - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RAX,AMD64_RAX,4); - p_exception = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_Z, 0, 1); - ppc32_jit_tcb_push_epilog(b); - - amd64_patch(p_exit,b->jit_ptr); - amd64_patch(p_exception,b->jit_ptr); -} + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RAX,AMD64_RAX,4); + p_exception = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); -/* Virtual Breakpoint */ -void ppc32_emit_breakpoint(ppc32_jit_tcb_t *b) -{ - amd64_mov_reg_reg(b->jit_ptr,AMD64_RDI,AMD64_R15,8); - ppc32_emit_c_call(b,ppc32_run_breakpoint); + amd64_patch(p_exit,iop->ob_ptr); + amd64_patch(p_exception,iop->ob_ptr); } /* Emit unhandled instruction code */ @@ -484,30 +616,44 @@ 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(&iop->ob_ptr,b->start_ia+(b->ppc_trans_pos << 2)); /* Fallback to non-JIT mode */ - amd64_mov_reg_reg(b->jit_ptr,AMD64_RDI,AMD64_R15,8); - amd64_mov_reg_imm(b->jit_ptr,AMD64_RSI,opcode); + amd64_mov_reg_reg(iop->ob_ptr,AMD64_RDI,AMD64_R15,8); + amd64_mov_reg_imm(iop->ob_ptr,AMD64_RSI,opcode); + + ppc32_emit_c_call(b,iop,ppc32_exec_single_insn_ext); + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RAX,AMD64_RAX,4); + test1 = iop->ob_ptr; + amd64_branch8(iop->ob_ptr, X86_CC_Z, 0, 1); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); - ppc32_emit_c_call(b,ppc32_exec_single_insn_ext); - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RAX,AMD64_RAX,4); - test1 = b->jit_ptr; - amd64_branch8(b->jit_ptr, X86_CC_Z, 0, 1); - ppc32_jit_tcb_push_epilog(b); + amd64_patch(test1,iop->ob_ptr); - amd64_patch(test1,b->jit_ptr); + /* Signal this as an EOB to reset JIT state */ + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); return(0); } +/* Virtual Breakpoint */ +void ppc32_emit_breakpoint(cpu_ppc_t *cpu,ppc32_jit_tcb_t *b) +{ + jit_op_t *iop; + + iop = ppc32_op_emit_insn_output(cpu,2,"breakpoint"); + + amd64_mov_reg_reg(iop->ob_ptr,AMD64_RDI,AMD64_R15,8); + 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); +} + /* Increment the number of executed instructions (performance debugging) */ void ppc32_inc_perf_counter(ppc32_jit_tcb_t *b) { @@ -519,32 +665,54 @@ /* BLR - Branch to Link Register */ DECLARE_INSN(BLR) { - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, - AMD64_R15,OFFSET(cpu_ppc_t,lr),4); - amd64_mov_membase_reg(b->jit_ptr, - AMD64_R15,OFFSET(cpu_ppc_t,ia),AMD64_RDX,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"); + + amd64_mov_reg_membase(iop->ob_ptr,hreg,AMD64_R15,OFFSET(cpu_ppc_t,lr),4); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,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) { - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, - AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ia), - AMD64_RDX,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"); + + amd64_mov_reg_membase(iop->ob_ptr,hreg,AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,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 << 2)); - ppc32_jit_tcb_push_epilog(b); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + ppc32_op_emit_branch_target(cpu,b,b->start_ia+((b->ppc_trans_pos+1) << 2)); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -552,10 +720,17 @@ DECLARE_INSN(MFLR) { int rd = bits(insn,21,25); - - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, - AMD64_R15,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"); + + amd64_mov_reg_membase(iop->ob_ptr,hreg_rd,AMD64_R15,OFFSET(cpu_ppc_t,lr),4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -563,10 +738,15 @@ 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); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,lr), - AMD64_RDX,4); + iop = ppc32_op_emit_insn_output(cpu,1,"mtlr"); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,lr),hreg_rs,4); return(0); } @@ -574,10 +754,19 @@ DECLARE_INSN(MFCTR) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, + ppc32_jit_start_hreg_seq(cpu,"mfctr"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + + iop = ppc32_op_emit_insn_output(cpu,1,"mfctr"); + + amd64_mov_reg_membase(iop->ob_ptr,hreg_rd, AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); - ppc32_store_gpr(b,rd,AMD64_RDX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -585,10 +774,19 @@ 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"); + + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ctr), + hreg_rs,4); - ppc32_load_gpr(b,AMD64_RDX,rs); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ctr), - AMD64_RDX,4); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -596,10 +794,19 @@ DECLARE_INSN(MFTBU) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, + ppc32_jit_start_hreg_seq(cpu,"mftbu"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); + + iop = ppc32_op_emit_insn_output(cpu,1,"mftbu"); + + amd64_mov_reg_membase(iop->ob_ptr,hreg_rd, AMD64_R15,OFFSET(cpu_ppc_t,tb)+4,4); - ppc32_store_gpr(b,rd,AMD64_RDX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -609,15 +816,23 @@ DECLARE_INSN(MFTBL) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"mftbl"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - /* Increment the time base register */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, + iop = ppc32_op_emit_insn_output(cpu,3,"mftbl"); + + amd64_mov_reg_membase(iop->ob_ptr,hreg_rd, AMD64_R15,OFFSET(cpu_ppc_t,tb),8); - amd64_alu_reg_imm(b->jit_ptr,X86_ADD,AMD64_RDX,PPC32_TB_INCREMENT); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,tb), - AMD64_RDX,8); + amd64_alu_reg_imm(iop->ob_ptr,X86_ADD,hreg_rd,PPC32_TB_INCREMENT); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,tb), + hreg_rd,8); + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); - ppc32_store_gpr(b,rd,AMD64_RDX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -627,15 +842,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,AMD64_RBX,ra); - ppc32_alu_gpr(b,X86_ADD,AMD64_RBX,rb); - ppc32_store_gpr(b,rd,AMD64_RBX); + 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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb,4); + else if (rd == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_rd,hreg_ra,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb,4); + } + + 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); } @@ -645,23 +880,46 @@ 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,AMD64_RBX,ra); - ppc32_alu_gpr(b,X86_ADD,AMD64_RBX,rb); - ppc32_store_gpr(b,rd,AMD64_RBX); + 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 */ - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RAX,FALSE); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x1); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - AMD64_RAX,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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb,4); + else if (rd == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_rd,hreg_ra,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_rd,hreg_rb,4); + } + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + /* store the carry flag */ + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t0,FALSE); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x1); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t0,4); if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - ppc32_update_cr0(b); + amd64_test_reg_reg_size(iop->ob_ptr,hreg_rd,hreg_rd,4); + ppc32_op_emit_update_flags(cpu,0,TRUE); } - + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -671,32 +929,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 + carry */ - ppc32_load_gpr(b,AMD64_RSI,ra); - amd64_alu_reg_membase_size(b->jit_ptr,X86_ADD,AMD64_RSI, - AMD64_R15,OFFSET(cpu_ppc_t,xer_ca),4); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RAX,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,AMD64_RSI,rb); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RCX,FALSE); + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); - ppc32_store_gpr(b,rd,AMD64_RSI); + 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 */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RAX,AMD64_RCX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x1); + iop = ppc32_op_emit_insn_output(cpu,3,"adde"); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - AMD64_RAX,4); + /* $t0 = $ra + carry */ + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + + amd64_alu_reg_membase_size(iop->ob_ptr,X86_ADD,hreg_t0, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca),4); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); + + /* $t0 += $rb */ + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb,4); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); /* update cr0 */ - if (insn & 1) { - x86_test_reg_reg(b->jit_ptr,AMD64_RSI,AMD64_RSI); - ppc32_update_cr0(b); - } + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_t0,hreg_t0,4); + + amd64_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); } @@ -707,14 +984,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); + + 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,2,"addi"); + + if (rd != ra) + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); - ppc32_load_imm(b,AMD64_RBX,tmp); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_rd,tmp,4); + } else { + iop = ppc32_op_emit_insn_output(cpu,1,"addi"); + ppc32_load_imm(&iop->ob_ptr,hreg_rd,tmp); + } - if (ra != 0) - amd64_alu_reg_membase_size(b->jit_ptr,X86_ADD,AMD64_RBX, - AMD64_R15,REG_OFFSET(ra),4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); - ppc32_store_gpr(b,rd,AMD64_RBX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -725,13 +1019,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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); - ppc32_load_imm(b,AMD64_RAX,tmp); - ppc32_alu_gpr(b,X86_ADD,AMD64_RAX,ra); - ppc32_store_gpr(b,rd,AMD64_RAX); - amd64_set_membase_size(b->jit_ptr,X86_CC_C, - AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - FALSE,4); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_rd,tmp,4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + amd64_set_membase(iop->ob_ptr,X86_CC_C, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca),FALSE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -742,16 +1051,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); - ppc32_load_imm(b,AMD64_RAX,tmp); - ppc32_alu_gpr(b,X86_ADD,AMD64_RAX,ra); - ppc32_store_gpr(b,rd,AMD64_RAX); - amd64_set_membase_size(b->jit_ptr,X86_CC_C, - AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - FALSE,4); + iop = ppc32_op_emit_insn_output(cpu,1,"addic."); - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RAX,AMD64_RAX,4); - ppc32_update_cr0(b); + if (rd != ra) + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_rd,tmp,4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + amd64_set_membase(iop->ob_ptr,X86_CC_C, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca),FALSE); + + ppc32_op_emit_update_flags(cpu,0,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -761,14 +1084,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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_rd,tmp,4); + } else { + iop = ppc32_op_emit_insn_output(cpu,1,"addis"); + amd64_mov_reg_imm(iop->ob_ptr,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; + + /* $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); + + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); + + iop = ppc32_op_emit_insn_output(cpu,2,"addze"); + + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,hreg_t0); + + if (rd != ra) + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + + amd64_alu_reg_membase_size(iop->ob_ptr,X86_ADD,hreg_rd, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca),4); + + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t0,FALSE); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t0,4); - ppc32_load_imm(b,AMD64_RBX,imm << 16); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); - if (ra != 0) - amd64_alu_reg_membase_size(b->jit_ptr,X86_ADD,AMD64_RBX, - AMD64_R15,REG_OFFSET(ra),4); + if (insn & 1) + ppc32_op_emit_update_flags(cpu,0,TRUE); - ppc32_store_gpr(b,rd,AMD64_RBX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -778,14 +1158,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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb,4); + else if (ra == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_rs,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb,4); + } - ppc32_load_gpr(b,AMD64_RBX,rs); - ppc32_alu_gpr(b,X86_AND,AMD64_RBX,rb); - ppc32_store_gpr(b,ra,AMD64_RBX); + 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); } @@ -795,16 +1196,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,AMD64_RBX,rb); - x86_not_reg(b->jit_ptr,AMD64_RBX); - ppc32_alu_gpr(b,X86_AND,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + 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); + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4); + amd64_not_reg(iop->ob_ptr,hreg_t0); + + /* $ra = $rs & $t0 */ + if (ra == rs) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_t0,4); + else { + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_t0,hreg_rs,4); + amd64_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); } @@ -814,13 +1238,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,AMD64_RBX,imm); - ppc32_alu_gpr(b,X86_AND,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + ppc32_jit_start_hreg_seq(cpu,"andi"); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); - ppc32_update_cr0(b); + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,2,"andi"); + + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_alu_reg_imm_size(iop->ob_ptr,X86_AND,hreg_ra,tmp,4); + 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); } @@ -830,13 +1269,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,AMD64_RBX,imm << 16); - ppc32_alu_gpr(b,X86_AND,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + 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); + + iop = ppc32_op_emit_insn_output(cpu,2,"andis"); + + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); - ppc32_update_cr0(b); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_AND,hreg_ra,tmp,4); + 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); } @@ -844,12 +1298,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); } @@ -857,11 +1318,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); } @@ -869,16 +1337,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); } @@ -886,15 +1360,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); } @@ -904,29 +1384,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); - amd64_test_membase_imm_size(b->jit_ptr, + ppc32_op_emit_require_flags(cpu,cr_field); + + amd64_test_membase_imm_size(iop->ob_ptr, AMD64_R15,PPC32_CR_FIELD_OFFSET(cr_field), (1 << cr_bit),4); @@ -937,54 +1426,65 @@ * page or not. */ if (local_jump) { - if (jump_ptr) { - amd64_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); - amd64_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); + amd64_branch32(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,0,FALSE); } else { - jump_ptr = b->jit_ptr; - amd64_branch32(b->jit_ptr,(cond) ? X86_CC_Z : X86_CC_NZ,0,FALSE); - ppc32_set_jump(cpu,b,new_ia,TRUE); - amd64_patch(jump_ptr,b->jit_ptr); + jump_ptr = iop->ob_ptr; + amd64_branch32(iop->ob_ptr,(cond) ? X86_CC_Z : X86_CC_NZ,0,FALSE); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); + amd64_patch(jump_ptr,iop->ob_ptr); } + ppc32_op_emit_branch_target(cpu,b,new_ia); return(0); } /* BC - Branch Conditional */ DECLARE_INSN(BC) -{ +{ 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); - ppc32_load_imm(b,AMD64_RAX,1); + amd64_mov_reg_imm(iop->ob_ptr,hreg_t0,1); /* Decrement the count register */ if (!(bo & 0x04)) { - amd64_dec_membase_size(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); - amd64_set_reg(b->jit_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,AMD64_RBX,FALSE); - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RAX,AMD64_RBX); + amd64_dec_membase_size(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); + amd64_set_reg(iop->ob_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,hreg_t1,FALSE); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } /* Test the condition bit */ @@ -992,15 +1492,17 @@ cr_field = ppc32_get_cr_field(bi); cr_bit = ppc32_get_cr_bit(bi); - amd64_test_membase_imm_size(b->jit_ptr, + ppc32_op_emit_require_flags(cpu,cr_field); + + amd64_test_membase_imm_size(iop->ob_ptr, AMD64_R15,PPC32_CR_FIELD_OFFSET(cr_field), (1 << cr_bit),4); - amd64_set_reg(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,AMD64_RCX,FALSE); - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RAX,AMD64_RCX); + amd64_set_reg(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,hreg_t1,FALSE); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x01); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); local_jump = ppc32_jit_tcb_local_addr(b,new_ia,&jump_ptr); @@ -1009,19 +1511,18 @@ * page or not. */ if (local_jump) { - if (jump_ptr) { - amd64_branch(b->jit_ptr,X86_CC_NZ,jump_ptr,FALSE); - } else { - ppc32_jit_tcb_record_patch(b,b->jit_ptr,new_ia); - amd64_branch32(b->jit_ptr,X86_CC_NZ,0,FALSE); - } + ppc32_jit_tcb_record_patch(b,iop,iop->ob_ptr,new_ia); + amd64_branch32(iop->ob_ptr,X86_CC_NZ,0,FALSE); } else { - jump_ptr = b->jit_ptr; - amd64_branch32(b->jit_ptr,X86_CC_Z,0,FALSE); - ppc32_set_jump(cpu,b,new_ia,TRUE); - amd64_patch(jump_ptr,b->jit_ptr); + jump_ptr = iop->ob_ptr; + amd64_branch32(iop->ob_ptr,X86_CC_Z,0,FALSE); + ppc32_set_jump(cpu,b,iop,new_ia,TRUE); + amd64_patch(jump_ptr,iop->ob_ptr); } + ppc32_op_emit_branch_target(cpu,b,new_ia); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1031,11 +1532,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; @@ -1043,15 +1554,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,AMD64_RAX,1); + amd64_mov_reg_imm(iop->ob_ptr,hreg_t0,1); /* Decrement the count register */ if (!(bo & 0x04)) { - amd64_dec_membase_size(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); - amd64_set_reg(b->jit_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,AMD64_RBX,FALSE); - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RAX,AMD64_RBX); + amd64_dec_membase_size(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ctr),4); + amd64_set_reg(iop->ob_ptr,(ctr) ? X86_CC_Z : X86_CC_NZ,hreg_t1,FALSE); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } /* Test the condition bit */ @@ -1059,33 +1570,39 @@ cr_field = ppc32_get_cr_field(bi); cr_bit = ppc32_get_cr_bit(bi); - amd64_test_membase_imm_size(b->jit_ptr, + ppc32_op_emit_require_flags(cpu,cr_field); + + amd64_test_membase_imm_size(iop->ob_ptr, AMD64_R15,PPC32_CR_FIELD_OFFSET(cr_field), (1 << cr_bit),4); - amd64_set_reg(b->jit_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,AMD64_RCX,FALSE); - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RAX,AMD64_RCX); + amd64_set_reg(iop->ob_ptr,(cond) ? X86_CC_NZ : X86_CC_Z,hreg_t1,FALSE); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,hreg_t1); } /* Set the return address */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, - AMD64_R15,OFFSET(cpu_ppc_t,lr),4); + amd64_mov_reg_membase(iop->ob_ptr,hreg_t1,AMD64_R15,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 */ - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x01); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); + + jump_ptr = iop->ob_ptr; + amd64_branch32(iop->ob_ptr,X86_CC_Z,0,FALSE); - jump_ptr = b->jit_ptr; - amd64_branch32(b->jit_ptr,X86_CC_Z,0,FALSE); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t1,0xFFFFFFFC); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ia),hreg_t1,4); + ppc32_jit_tcb_push_epilog(&iop->ob_ptr); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RDX,0xFFFFFFFC); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,ia), - AMD64_RDX,4); - ppc32_jit_tcb_push_epilog(b); + amd64_patch(jump_ptr,iop->ob_ptr); - amd64_patch(jump_ptr,b->jit_ptr); + ppc32_op_emit_basic_opcode(cpu,JIT_OP_EOB); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1095,10 +1612,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,AMD64_RBX,ra); - ppc32_alu_gpr(b,X86_CMP,AMD64_RBX,rb); - ppc32_update_cr(b,rd,TRUE); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_CMP,hreg_ra,hreg_rb,4); + ppc32_op_emit_update_flags(cpu,rd,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1109,12 +1638,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,AMD64_RBX,tmp); - ppc32_load_gpr(b,AMD64_RSI,ra); - amd64_alu_reg_reg_size(b->jit_ptr,X86_CMP,AMD64_RSI,AMD64_RBX,4); + iop = ppc32_op_emit_insn_output(cpu,1,"cmpi"); - ppc32_update_cr(b,rd,TRUE); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_CMP,hreg_ra,tmp,4); + ppc32_op_emit_update_flags(cpu,rd,TRUE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1124,10 +1660,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_load_gpr(b,AMD64_RAX,ra); - ppc32_alu_gpr(b,X86_CMP,AMD64_RAX,rb); - ppc32_update_cr(b,rd,FALSE); + 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"); + + amd64_alu_reg_reg_size(iop->ob_ptr,X86_CMP,hreg_ra,hreg_rb,4); + ppc32_op_emit_update_flags(cpu,rd,FALSE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1136,13 +1684,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,AMD64_RBX,imm); - ppc32_load_gpr(b,AMD64_RSI,ra); - amd64_alu_reg_reg_size(b->jit_ptr,X86_CMP,AMD64_RSI,AMD64_RBX,4); + iop = ppc32_op_emit_insn_output(cpu,1,"cmpli"); - ppc32_update_cr(b,rd,FALSE); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_CMP,hreg_ra,imm,4); + ppc32_op_emit_update_flags(cpu,rd,FALSE); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1152,36 +1707,52 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"crand"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of AND between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RBX,AMD64_RAX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,AMD64_RDX); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1191,36 +1762,52 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"crandc"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_Z,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_Z,hreg_t0,FALSE); /* result of AND between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RBX,AMD64_RAX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,AMD64_RDX); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1230,37 +1817,53 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"creqv"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of XOR between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_XOR,AMD64_RBX,AMD64_RAX); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,AMD64_RDX); + amd64_not_reg(iop->ob_ptr,hreg_t0); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1270,37 +1873,53 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"crnand"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of NAND between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_AND,AMD64_RBX,AMD64_RAX); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_AND,hreg_t0,AMD64_RDX); + amd64_not_reg(iop->ob_ptr,hreg_t0); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1310,37 +1929,53 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"crnor"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of NOR between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RBX,AMD64_RAX); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,AMD64_RDX); + amd64_not_reg(iop->ob_ptr,hreg_t0); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1350,36 +1985,52 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"cror"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of NOR between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RBX,AMD64_RAX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,AMD64_RDX); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1389,36 +2040,52 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"crorc"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_Z,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_Z,hreg_t0,FALSE); /* result of ORC between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RBX,AMD64_RAX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_t0,AMD64_RDX); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1428,36 +2095,52 @@ 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,AMD64_RDX); + + ppc32_jit_start_hreg_seq(cpu,"crxor"); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + + 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 */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(ba)), (1 << ppc32_get_cr_bit(ba))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RAX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,AMD64_RDX,FALSE); /* test $bb bit */ - amd64_test_membase_imm(b->jit_ptr, + amd64_test_membase_imm(iop->ob_ptr, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bb)), (1 << ppc32_get_cr_bit(bb))); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RBX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_NZ,hreg_t0,FALSE); /* result of XOR between $ba and $bb */ - amd64_alu_reg_reg(b->jit_ptr,X86_XOR,AMD64_RBX,AMD64_RAX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,0x01); + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t0,AMD64_RDX); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x01); /* set/clear $bd bit depending on the result */ - amd64_alu_membase_imm_size(b->jit_ptr,X86_AND, + amd64_alu_membase_imm_size(iop->ob_ptr,X86_AND, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), ~(1 << ppc32_get_cr_bit(bd)),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RBX,ppc32_get_cr_bit(bd)); - amd64_alu_membase_reg_size(b->jit_ptr,X86_OR, + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_t0,ppc32_get_cr_bit(bd)); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, AMD64_R15, PPC32_CR_FIELD_OFFSET(ppc32_get_cr_field(bd)), - AMD64_RBX,4); + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1467,19 +2150,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,AMD64_RAX,ra); - ppc32_load_gpr(b,AMD64_RBX,rb); - ppc32_load_imm(b,AMD64_RDX,0); + ppc32_jit_start_hreg_seq(cpu,"divwu"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RAX); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + /* $rd = $ra / $rb */ + ppc32_op_emit_load_gpr(cpu,AMD64_RAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); - amd64_div_reg_size(b->jit_ptr,AMD64_RBX,0,4); - ppc32_store_gpr(b,rd,AMD64_RAX); + iop = ppc32_op_emit_insn_output(cpu,2,"divwu"); + ppc32_load_imm(&iop->ob_ptr,AMD64_RDX,0); - if (insn & 1) { - amd64_test_reg_reg(b->jit_ptr,AMD64_RAX,AMD64_RAX); - ppc32_update_cr0(b); - } - + amd64_div_reg_size(iop->ob_ptr,hreg_rb,0,4); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RAX,AMD64_RAX,4); + + ppc32_op_emit_store_gpr(cpu,rd,AMD64_RAX); + + 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,AMD64_RAX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1489,18 +2189,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,AMD64_RBX,rs); - ppc32_alu_gpr(b,X86_XOR,AMD64_RBX,rb); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - ppc32_store_gpr(b,ra,AMD64_RBX); - - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb,4); + else if (ra == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rs,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb,4); } + amd64_not_reg(iop->ob_ptr,hreg_ra); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -1509,17 +2231,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,AMD64_RBX,rs); - amd64_shift_reg_imm_size(b->jit_ptr,X86_SHL,AMD64_RBX,24,4); - amd64_shift_reg_imm_size(b->jit_ptr,X86_SAR,AMD64_RBX,24,4); - ppc32_store_gpr(b,ra,AMD64_RBX); + /* $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) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_shift_reg_imm_size(iop->ob_ptr,X86_SHL,hreg_ra,24,4); + amd64_shift_reg_imm_size(iop->ob_ptr,X86_SAR,hreg_ra,24,4); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -1528,17 +2266,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,AMD64_RBX,rs); - amd64_shift_reg_imm_size(b->jit_ptr,X86_SHL,AMD64_RBX,16,4); - amd64_shift_reg_imm_size(b->jit_ptr,X86_SAR,AMD64_RBX,16,4); - ppc32_store_gpr(b,ra,AMD64_RBX); + /* $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) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_shift_reg_imm_size(iop->ob_ptr,X86_SHL,hreg_ra,16,4); + amd64_shift_reg_imm_size(iop->ob_ptr,X86_SAR,hreg_ra,16,4); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -1550,7 +2304,8 @@ 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_fast(cpu,b,0,PPC_MEMOP_LBZ,ra,offset,rs, + ppc32_memop_fast_lbz); return(0); } @@ -1561,7 +2316,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); } @@ -1572,7 +2327,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); } @@ -1583,7 +2338,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); } @@ -1594,7 +2349,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); } @@ -1605,7 +2360,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); } @@ -1616,7 +2371,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); } @@ -1627,7 +2382,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); } @@ -1638,7 +2393,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); } @@ -1649,7 +2404,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); } @@ -1660,7 +2415,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); } @@ -1671,7 +2426,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); } @@ -1683,7 +2438,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); } @@ -1694,7 +2450,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); } @@ -1705,7 +2461,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); } @@ -1716,7 +2472,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); } @@ -1725,14 +2481,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); - /* Load "rs" field in %rdx */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, + iop = ppc32_op_emit_insn_output(cpu,1,"mcrf"); + + /* Load "rs" field in %edx */ + amd64_mov_reg_membase(iop->ob_ptr,hreg_t0, AMD64_R15,PPC32_CR_FIELD_OFFSET(rs),4); /* Store it in "rd" field */ - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,PPC32_CR_FIELD_OFFSET(rd), - AMD64_RDX,4); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,PPC32_CR_FIELD_OFFSET(rd), + hreg_t0,4); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1740,19 +2506,30 @@ DECLARE_INSN(MFCR) { int rd = bits(insn,21,25); + int hreg_rd,hreg_t0; + jit_op_t *iop; int i; - - amd64_alu_reg_reg(b->jit_ptr,X86_XOR,AMD64_RAX,AMD64_RAX); + + 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"); + + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_rd,hreg_rd); for(i=0;i<8;i++) { - /* load field in %rdx */ - amd64_mov_reg_membase(b->jit_ptr,AMD64_RDX, + /* load field in %edx */ + amd64_mov_reg_membase(iop->ob_ptr,hreg_t0, AMD64_R15,PPC32_CR_FIELD_OFFSET(i),4); - amd64_shift_reg_imm(b->jit_ptr,X86_SHL,AMD64_RAX,4); - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RAX,AMD64_RDX); + amd64_shift_reg_imm(iop->ob_ptr,X86_SHL,hreg_rd,4); + amd64_alu_reg_reg(iop->ob_ptr,X86_OR,hreg_rd,hreg_t0); } - ppc32_store_gpr(b,rd,AMD64_RAX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1760,10 +2537,18 @@ DECLARE_INSN(MFMSR) { int rd = bits(insn,21,25); + int hreg_rd; + jit_op_t *iop; + + ppc32_jit_start_hreg_seq(cpu,"mfmsr"); + hreg_rd = ppc32_jit_alloc_hreg(cpu,rd); - amd64_mov_reg_membase(b->jit_ptr,AMD64_RAX, + iop = ppc32_op_emit_insn_output(cpu,1,"mfmsr"); + amd64_mov_reg_membase(iop->ob_ptr,hreg_rd, AMD64_R15,OFFSET(cpu_ppc_t,msr),4); - ppc32_store_gpr(b,rd,AMD64_RAX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1772,10 +2557,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); + + iop = ppc32_op_emit_insn_output(cpu,1,"mfsr"); - amd64_mov_reg_membase(b->jit_ptr,AMD64_RAX, + amd64_mov_reg_membase(iop->ob_ptr,hreg_rd, AMD64_R15,(OFFSET(cpu_ppc_t,sr) + (sr << 2)),4); - ppc32_store_gpr(b,rd,AMD64_RAX); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1784,22 +2578,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,AMD64_RDX,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))) { - amd64_mov_reg_reg(b->jit_ptr,AMD64_RAX,AMD64_RDX,8); + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); if (i != 7) - amd64_shift_reg_imm(b->jit_ptr,X86_SHR,AMD64_RAX,28 - (i << 2)); + amd64_shift_reg_imm(iop->ob_ptr,X86_SHR,hreg_t0,28 - (i << 2)); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x0F); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,PPC32_CR_FIELD_OFFSET(i), - AMD64_RAX,4); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x0F); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,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); } @@ -1809,17 +2614,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,AMD64_RAX,ra); - ppc32_load_gpr(b,AMD64_RBX,rb); - amd64_mul_reg_size(b->jit_ptr,AMD64_RBX,1,4); - ppc32_store_gpr(b,rd,AMD64_RDX); + ppc32_jit_start_hreg_seq(cpu,"mulhw"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RAX); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,AMD64_RAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + /* rd = hi(ra * rb) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mulhw"); + amd64_mul_reg_size(iop->ob_ptr,hreg_rb,1,4); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RDX,AMD64_RDX,4); - ppc32_update_cr0(b); - } + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RDX,AMD64_RDX,4); + + ppc32_op_emit_store_gpr(cpu,rd,AMD64_RDX); + + 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,AMD64_RAX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1829,17 +2651,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,AMD64_RAX,ra); - ppc32_load_gpr(b,AMD64_RBX,rb); - amd64_mul_reg_size(b->jit_ptr,AMD64_RBX,0,4); - ppc32_store_gpr(b,rd,AMD64_RDX); + ppc32_jit_start_hreg_seq(cpu,"mulhwu"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RAX); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,AMD64_RAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + /* rd = hi(ra * rb) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mulhwu"); + amd64_mul_reg_size(iop->ob_ptr,hreg_rb,0,4); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RDX,AMD64_RDX,4); - ppc32_update_cr0(b); - } + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RDX,AMD64_RDX,4); + + ppc32_op_emit_store_gpr(cpu,rd,AMD64_RDX); + + 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,AMD64_RAX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1849,12 +2688,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,AMD64_RAX); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + hreg_t0 = ppc32_jit_get_tmp_hreg(cpu); + + ppc32_op_emit_load_gpr(cpu,AMD64_RAX,ra); - ppc32_load_gpr(b,AMD64_RAX,ra); - ppc32_load_imm(b,AMD64_RBX,sign_extend_32(imm,16)); + /* rd = lo(ra * imm) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mulli"); - amd64_mul_reg_size(b->jit_ptr,AMD64_RBX,1,4); - ppc32_store_gpr(b,rd,X86_EAX); + ppc32_load_imm(&iop->ob_ptr,hreg_t0,sign_extend_32(imm,16)); + amd64_mul_reg_size(iop->ob_ptr,hreg_t0,1,4); + ppc32_op_emit_store_gpr(cpu,rd,AMD64_RAX); + + /* edx:eax are directly modified: throw them */ + ppc32_op_emit_alter_host_reg(cpu,AMD64_RAX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1864,17 +2719,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,AMD64_RAX,ra); - ppc32_load_gpr(b,AMD64_RBX,rb); - amd64_mul_reg_size(b->jit_ptr,AMD64_RBX,1,4); - ppc32_store_gpr(b,rd,AMD64_RAX); + ppc32_jit_start_hreg_seq(cpu,"mullw"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RAX); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RDX); + hreg_rb = ppc32_jit_alloc_hreg(cpu,rb); + + ppc32_op_emit_load_gpr(cpu,AMD64_RAX,ra); + ppc32_op_emit_load_gpr(cpu,hreg_rb,rb); + + /* rd = lo(ra * rb) */ + iop = ppc32_op_emit_insn_output(cpu,2,"mullw"); + amd64_mul_reg_size(iop->ob_ptr,hreg_rb,1,4); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RAX,AMD64_RAX,4); - ppc32_update_cr0(b); - } + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,AMD64_RAX,AMD64_RAX,4); + ppc32_op_emit_store_gpr(cpu,rd,AMD64_RAX); + + 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,AMD64_RAX); + ppc32_op_emit_alter_host_reg(cpu,AMD64_RDX); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -1884,18 +2756,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,AMD64_RBX,rs); - ppc32_alu_gpr(b,X86_AND,AMD64_RBX,rb); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - ppc32_store_gpr(b,ra,AMD64_RBX); - - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb,4); + else if (ra == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_rs,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_AND,hreg_ra,hreg_rb,4); } + amd64_not_reg(iop->ob_ptr,hreg_ra); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -1904,16 +2798,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,AMD64_RBX,ra); - amd64_neg_reg(b->jit_ptr,AMD64_RBX); - ppc32_store_gpr(b,rd,AMD64_RBX); + /* $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) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_ra,4); + amd64_neg_reg(iop->ob_ptr,hreg_rd); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_rd,hreg_rd,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); } @@ -1923,18 +2833,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,AMD64_RBX,rs); - ppc32_alu_gpr(b,X86_OR,AMD64_RBX,rb); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - ppc32_store_gpr(b,ra,AMD64_RBX); - - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb,4); + else if (ra == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_rs,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb,4); } + amd64_not_reg(iop->ob_ptr,hreg_ra); + + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -1944,20 +2876,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,AMD64_RCX,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,AMD64_RCX,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,AMD64_RCX); + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); - if (insn & 1) { - if (rs == rb) - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RCX,AMD64_RCX,4); - ppc32_update_cr0(b); + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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) { + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb,4); + } else if (ra == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_rs,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_rb,4); + } + + 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); } @@ -1967,16 +2934,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_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); + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4); + amd64_not_reg(iop->ob_ptr,hreg_t0); + + /* $ra = $rs | $t0 */ + if (ra == rs) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_ra,hreg_t0,4); + else { + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,hreg_t0,hreg_rs,4); + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); + } - /* $ra = $rs | ~$rb */ - ppc32_load_gpr(b,AMD64_RBX,rb); - amd64_not_reg(b->jit_ptr,AMD64_RBX); - ppc32_alu_gpr(b,X86_OR,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + 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); } @@ -1986,12 +2976,27 @@ 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,AMD64_RBX,imm); - ppc32_alu_gpr(b,X86_OR,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); - return(0); + 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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_alu_reg_imm_size(iop->ob_ptr,X86_OR,hreg_ra,tmp,4); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + ppc32_jit_close_hreg_seq(cpu); + return(0); } /* OR Immediate Shifted */ @@ -1999,12 +3004,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); - /* $ra = $rs | (imm << 16) */ - ppc32_load_imm(b,AMD64_RBX,imm << 16); - ppc32_alu_gpr(b,X86_OR,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + + iop = ppc32_op_emit_insn_output(cpu,1,"oris"); + + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_alu_reg_imm_size(iop->ob_ptr,X86_OR,hreg_ra,tmp,4); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); + + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2017,30 +3037,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,AMD64_RAX,ra); + iop = ppc32_op_emit_insn_output(cpu,2,"rlwimi"); + + /* Apply inverse mask to $ra */ if (mask != 0) - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,~mask); + amd64_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,AMD64_RBX,rs); + /* Rotate $rs of "sh" bits and apply the mask */ + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); if (sh != 0) - amd64_shift_reg_imm_size(b->jit_ptr,X86_ROL,AMD64_RBX,sh,4); + amd64_shift_reg_imm_size(iop->ob_ptr,X86_ROL,hreg_t0,sh,4); if (mask != 0xFFFFFFFF) - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,mask); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask); /* Store the result */ - amd64_alu_reg_reg_size(b->jit_ptr,X86_OR,AMD64_RBX,AMD64_RAX,4); - ppc32_store_gpr(b,ra,AMD64_RBX); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_OR,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); } @@ -2053,25 +3085,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,AMD64_RBX,rs); + if (rs != ra) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); if (sh != 0) - amd64_shift_reg_imm_size(b->jit_ptr,X86_ROL,AMD64_RBX,sh,4); + amd64_shift_reg_imm_size(iop->ob_ptr,X86_ROL,hreg_ra,sh,4); if (mask != 0xFFFFFFFF) - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,mask); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_ra,mask); - ppc32_store_gpr(b,ra,AMD64_RBX); + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - 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); } @@ -2084,26 +3129,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,AMD64_RCX); + + ppc32_jit_start_hreg_seq(cpu,"rlwnm"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RCX); + + 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,AMD64_RCX,rb); + + iop = ppc32_op_emit_insn_output(cpu,2,"rlwnm"); /* Load the shift register ("sh") */ - ppc32_load_gpr(b,AMD64_RCX,rb); + mask = ppc32_rotate_mask(mb,me); - /* Rotate %ebx ("rs") and apply the mask */ - ppc32_load_gpr(b,AMD64_RBX,rs); - amd64_shift_reg_size(b->jit_ptr,X86_ROL,AMD64_RBX,4); + /* Rotate $rs and apply the mask */ + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); + + amd64_shift_reg_size(iop->ob_ptr,X86_ROL,hreg_t0,4); if (mask != 0xFFFFFFFF) - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RBX,mask); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask); - ppc32_store_gpr(b,ra,AMD64_RBX); + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_t0,4); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - ppc32_update_cr0(b); - } + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -2113,22 +3179,40 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra; + jit_op_t *iop; - /* If count >= 32, then null result */ - ppc32_load_gpr(b,AMD64_RCX,rb); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RCX,0x3f); + /* ecx is directly modified: throw it */ + ppc32_op_emit_alter_host_reg(cpu,AMD64_RCX); - ppc32_load_gpr(b,AMD64_RBX,rs); - amd64_shift_reg(b->jit_ptr,X86_SHL,AMD64_RBX); + ppc32_jit_start_hreg_seq(cpu,"slw"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RCX); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); - /* Store the result */ - ppc32_store_gpr(b,ra,AMD64_RBX); + /* $ra = $rs << $rb. If count >= 32, then null result */ + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,AMD64_RCX,rb); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - ppc32_update_cr0(b); - } + iop = ppc32_op_emit_insn_output(cpu,3,"slw"); + + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,AMD64_RCX,0x3f); + + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_shift_reg(iop->ob_ptr,X86_SHL,hreg_ra); + + /* store the result */ + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + 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,32 +3223,43 @@ 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,AMD64_RBX,rs); - amd64_mov_reg_reg(b->jit_ptr,AMD64_RSI,AMD64_RBX,4); - amd64_shift_reg_imm_size(b->jit_ptr,X86_SAR,AMD64_RBX,sh,4); - ppc32_store_gpr(b,ra,AMD64_RBX); - - /* test the sign-bit of gpr[rs] */ - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RSI,AMD64_RSI,4); - amd64_set_reg(b->jit_ptr,X86_CC_LT,AMD64_RAX,TRUE); - - amd64_alu_reg_imm_size(b->jit_ptr,X86_AND,AMD64_RSI,mask,4); - amd64_set_reg(b->jit_ptr,X86_CC_NZ,AMD64_RCX,TRUE); - - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RCX,AMD64_RAX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RCX,0x1); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - AMD64_RCX,4); + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - ppc32_update_cr0(b); - } + iop = ppc32_op_emit_insn_output(cpu,3,"srawi"); + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rs,4); + + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_shift_reg_imm_size(iop->ob_ptr,X86_SAR,hreg_ra,sh,4); + + /* set XER_CA depending on the result */ + mask = ~(0xFFFFFFFFU << sh) | 0x80000000; + + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,mask); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_CMP,hreg_t0,0x80000000,4); + amd64_set_reg(iop->ob_ptr,X86_CC_A,hreg_t0,FALSE); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,hreg_t0,0x1); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t0,4); + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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,22 +3269,40 @@ int rs = bits(insn,21,25); int ra = bits(insn,16,20); int rb = bits(insn,11,15); + int hreg_rs,hreg_ra; + jit_op_t *iop; - /* If count >= 32, then null result */ - ppc32_load_gpr(b,AMD64_RCX,rb); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RCX,0x3f); + /* ecx is directly modified: throw it */ + ppc32_op_emit_alter_host_reg(cpu,AMD64_RCX); - ppc32_load_gpr(b,AMD64_RBX,rs); - amd64_shift_reg(b->jit_ptr,X86_SHR,AMD64_RBX); + ppc32_jit_start_hreg_seq(cpu,"srw"); + ppc32_jit_alloc_hreg_forced(cpu,AMD64_RCX); + hreg_rs = ppc32_jit_alloc_hreg(cpu,rs); + hreg_ra = ppc32_jit_alloc_hreg(cpu,ra); - /* Store the result */ - ppc32_store_gpr(b,ra,AMD64_RBX); + /* $ra = $rs >> $rb. If count >= 32, then null result */ + ppc32_op_emit_load_gpr(cpu,hreg_rs,rs); + ppc32_op_emit_load_gpr(cpu,AMD64_RCX,rb); - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RBX,AMD64_RBX,4); - ppc32_update_cr0(b); - } + iop = ppc32_op_emit_insn_output(cpu,3,"srw"); + amd64_alu_reg_imm(iop->ob_ptr,X86_AND,AMD64_RCX,0x3f); + + if (ra != rs) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_shift_reg(iop->ob_ptr,X86_SHR,hreg_ra); + + /* store the result */ + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_ra,hreg_ra,4); + + 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); } @@ -2201,7 +3314,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); } @@ -2212,7 +3326,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); } @@ -2223,7 +3337,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); } @@ -2234,7 +3348,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); } @@ -2245,7 +3359,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); } @@ -2256,7 +3370,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); } @@ -2267,7 +3381,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); } @@ -2278,7 +3392,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); } @@ -2290,7 +3404,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); } @@ -2301,7 +3416,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); } @@ -2312,7 +3427,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); } @@ -2323,7 +3438,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); } @@ -2333,15 +3448,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 - $rb */ - ppc32_load_gpr(b,AMD64_RBX,rb); - ppc32_alu_gpr(b,X86_SUB,AMD64_RBX,ra); - ppc32_store_gpr(b,rd,AMD64_RBX); + /* $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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_SUB,hreg_rd,hreg_ra,4); + else if (rd == ra) { + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_rb,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_SUB,hreg_t0,hreg_ra,4); + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); + } else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_rb,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_SUB,hreg_rd,hreg_ra,4); + } + + 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); } @@ -2351,32 +3490,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 + 1 */ - ppc32_load_gpr(b,AMD64_RSI,ra); - amd64_not_reg(b->jit_ptr,AMD64_RSI); - amd64_alu_reg_imm_size(b->jit_ptr,X86_ADD,AMD64_RSI,1,4); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RAX,FALSE); - - /* add $rb */ - ppc32_alu_gpr(b,X86_ADD,AMD64_RSI,rb); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RCX,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"); + + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + + /* $t0 = ~$ra + 1 */ + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + amd64_not_reg(iop->ob_ptr,hreg_t0); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_t0,1,4); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); + + /* $t0 += $rb */ + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb,4); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); - ppc32_store_gpr(b,rd,AMD64_RSI); + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); - /* store the carry flag */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RAX,AMD64_RCX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x1); + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_rd,hreg_rd,4); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - AMD64_RAX,4); + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); /* update cr0 */ - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RSI,AMD64_RSI,4); + if (insn & 1) ppc32_update_cr0(b); - } + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2386,32 +3546,55 @@ 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,AMD64_RSI,ra); - amd64_not_reg(b->jit_ptr,AMD64_RSI); - amd64_alu_reg_membase_size(b->jit_ptr,X86_ADD,AMD64_RSI, + /* $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"); + + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + + /* $t0 = ~$ra + $carry */ + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + amd64_not_reg(iop->ob_ptr,hreg_t0); + amd64_alu_reg_membase_size(iop->ob_ptr,X86_ADD,hreg_t0, AMD64_R15,OFFSET(cpu_ppc_t,xer_ca),4); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RAX,FALSE); - /* add $rb */ - ppc32_alu_gpr(b,X86_ADD,AMD64_RSI,rb); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RCX,FALSE); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); + + /* $t0 += $rb */ + amd64_alu_reg_reg_size(iop->ob_ptr,X86_ADD,hreg_t0,hreg_rb,4); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); - ppc32_store_gpr(b,rd,AMD64_RSI); + amd64_mov_reg_reg(iop->ob_ptr,hreg_rd,hreg_t0,4); - /* store the carry flag */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RAX,AMD64_RCX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x1); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - AMD64_RAX,4); + if (insn & 1) + amd64_test_reg_reg_size(iop->ob_ptr,hreg_rd,hreg_rd,4); + + ppc32_op_emit_store_gpr(cpu,rd,hreg_rd); /* update cr0 */ - if (insn & 1) { - amd64_test_reg_reg_size(b->jit_ptr,AMD64_RSI,AMD64_RSI,4); + if (insn & 1) ppc32_update_cr0(b); - } + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2422,25 +3605,44 @@ 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,AMD64_RSI,ra); - amd64_not_reg(b->jit_ptr,AMD64_RSI); - amd64_alu_reg_imm_size(b->jit_ptr,X86_ADD,AMD64_RSI,1,4); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RAX,FALSE); - - /* add sign-extended $immediate */ - amd64_alu_reg_imm_size(b->jit_ptr,X86_ADD,AMD64_RSI,tmp,4); - amd64_set_reg(b->jit_ptr,X86_CC_C,AMD64_RCX,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,AMD64_RSI); + hreg_t0 = ppc32_jit_alloc_hreg(cpu,-1); + hreg_t1 = ppc32_jit_get_tmp_hreg(cpu); - /* store the carry flag */ - amd64_alu_reg_reg(b->jit_ptr,X86_OR,AMD64_RAX,AMD64_RCX); - amd64_alu_reg_imm(b->jit_ptr,X86_AND,AMD64_RAX,0x1); + ppc32_op_emit_alter_host_reg(cpu,hreg_t0); + ppc32_op_emit_load_gpr(cpu,hreg_ra,ra); - amd64_mov_membase_reg(b->jit_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), - AMD64_RAX,4); + iop = ppc32_op_emit_insn_output(cpu,3,"subfic"); + + amd64_alu_reg_reg(iop->ob_ptr,X86_XOR,hreg_t1,hreg_t1); + + /* $t0 = ~$ra + 1 */ + amd64_mov_reg_reg(iop->ob_ptr,hreg_t0,hreg_ra,4); + amd64_not_reg(iop->ob_ptr,hreg_t0); + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_t0,1,4); + + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_mov_membase_reg(iop->ob_ptr,AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); + + /* $t0 += sign_extend(imm,16) */ + amd64_alu_reg_imm_size(iop->ob_ptr,X86_ADD,hreg_t0,tmp,4); + amd64_set_reg(iop->ob_ptr,X86_CC_C,hreg_t1,FALSE); + amd64_alu_membase_reg_size(iop->ob_ptr,X86_OR, + AMD64_R15,OFFSET(cpu_ppc_t,xer_ca), + hreg_t1,4); + + amd64_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); } @@ -2456,14 +3658,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) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb,4); + else if (ra == rb) + amd64_alu_reg_reg_size(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rs,4); + else { + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + amd64_alu_reg_reg_size(iop->ob_ptr,X86_XOR,hreg_ra,hreg_rb,4); + } - ppc32_load_gpr(b,AMD64_RBX,rs); - ppc32_alu_gpr(b,X86_XOR,AMD64_RBX,rb); - ppc32_store_gpr(b,ra,AMD64_RBX); + 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); } @@ -2473,10 +3696,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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); - ppc32_load_imm(b,AMD64_RBX,imm); - ppc32_alu_gpr(b,X86_XOR,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + amd64_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); } @@ -2485,11 +3723,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) + amd64_mov_reg_reg(iop->ob_ptr,hreg_ra,hreg_rs,4); + + amd64_alu_reg_imm(iop->ob_ptr,X86_XOR,hreg_ra,tmp); + ppc32_op_emit_store_gpr(cpu,ra,hreg_ra); - ppc32_load_imm(b,AMD64_RBX,imm << 16); - ppc32_alu_gpr(b,X86_XOR,AMD64_RBX,rs); - ppc32_store_gpr(b,ra,AMD64_RBX); + ppc32_jit_close_hreg_seq(cpu); return(0); } @@ -2510,6 +3764,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 },