void genc_ngt_s(void) { #ifdef INTERPRET_C_NGT_S gencallinterp((native_type)cached_interpreter_table.C_NGT_S, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.ft])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); fcomip_fpreg(1); ffree_fpreg(0); jp_rj(15); ja_rj(13); or_m32rel_imm32((unsigned int*)&FCR31, 0x800000); // 11 jmp_imm_short(11); // 2 and_m32rel_imm32((unsigned int*)&FCR31, ~0x800000); // 11 #else mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.ft])); fld_preg32_dword(EAX); mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fs])); fld_preg32_dword(EAX); fcomip_fpreg(1); ffree_fpreg(0); jp_rj(14); ja_rj(12); or_m32_imm32((unsigned int*)&FCR31, 0x800000); // 10 jmp_imm_short(10); // 2 and_m32_imm32((unsigned int*)&FCR31, ~0x800000); // 10 #endif #endif }
void genc_sf_s(void) { #ifdef INTERPRET_C_SF_S gencallinterp((native_type)cached_interpreter_table.C_SF_S, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.ft])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); fcomip_fpreg(1); ffree_fpreg(0); and_m32rel_imm32((unsigned int*)&FCR31, ~0x800000); #else mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.ft])); fld_preg32_dword(EAX); mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fs])); fld_preg32_dword(EAX); fcomip_fpreg(1); ffree_fpreg(0); and_m32_imm32((unsigned int*)&FCR31, ~0x800000); #endif #endif }
void gencvt_l_s(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[117]); #endif #ifdef INTERPRET_CVT_L_S gencallinterp((unsigned long long)cached_interpreter_table.CVT_L_S, 0); #else gencheck_cop1_unusable(); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_double[dst->f.cf.fd])); fistp_preg64_qword(RAX); #endif }
void genmov_s(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[125]); #endif #ifdef INTERPRET_MOV_S gencallinterp((unsigned long long)cached_interpreter_table.MOV_S, 0); #else gencheck_cop1_unusable(); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); mov_reg32_preg64(EBX, RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fd])); mov_preg64_reg32(RAX, EBX); #endif }
void genfloor_w_s(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[130]); #endif #ifdef INTERPRET_FLOOR_W_S gencallinterp((unsigned long long)cached_interpreter_table.FLOOR_W_S, 0); #else gencheck_cop1_unusable(); fldcw_m16rel((unsigned short*)&floor_mode); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fd])); fistp_preg64_dword(RAX); fldcw_m16rel((unsigned short*)&rounding_mode); #endif }
void gendmultu(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[76]); #endif #ifdef INTERPRET_DMULTU gencallinterp((unsigned long long)cached_interpreter_table.DMULTU, 0); #else free_registers_move_start(); mov_xreg64_m64rel(RAX, (unsigned long long *) dst->f.r.rs); mov_xreg64_m64rel(RDX, (unsigned long long *) dst->f.r.rt); mul_reg64(RDX); mov_m64rel_xreg64((unsigned long long *) &lo, RAX); mov_m64rel_xreg64((unsigned long long *) &hi, RDX); #endif }
// this function is similar to allocate_register except it loads // a 64 bits value, and return the register number of the LSB part int allocate_register_64(unsigned long long *addr) { int reg, i; // is it already cached? if (addr != NULL) { for (i = 0; i < 8; i++) { if (last_access[i] != NULL && reg_content[i] == addr) { precomp_instr *last = last_access[i]+1; while (last <= dst) { last->reg_cache_infos.needed_registers[i] = reg_content[i]; last++; } last_access[i] = dst; if (is64bits[i] == 0) { movsxd_reg64_reg32(i, i); is64bits[i] = 1; } return i; } } } // it's not cached, so take the least recently used register reg = lru_register(); if (last_access[reg]) free_register(reg); else { while (free_since[reg] <= dst) { free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL; free_since[reg]++; } } last_access[reg] = dst; reg_content[reg] = addr; dirty[reg] = 0; is64bits[reg] = 1; if (addr != NULL) { if (addr == r0) xor_reg64_reg64(reg, reg); else mov_xreg64_m64rel(reg, addr); } return reg; }
// this function is similar to allocate_register except it loads // a 64 bits value, and return the register number of the LSB part int allocate_register_64(usf_state_t * state, unsigned long long *addr) { int reg, i; // is it already cached? if (addr != NULL) { for (i = 0; i < 8; i++) { if (state->last_access[i] != NULL && state->reg_content[i] == addr) { precomp_instr *last = state->last_access[i]+1; while (last <= state->dst) { last->reg_cache_infos.needed_registers[i] = state->reg_content[i]; last++; } state->last_access[i] = state->dst; if (state->is64bits[i] == 0) { movsxd_reg64_reg32(state, i, i); state->is64bits[i] = 1; } return i; } } } // it's not cached, so take the least recently used register reg = lru_register(state); if (state->last_access[reg]) free_register(state, reg); else { while (state->free_since[reg] <= state->dst) { state->free_since[reg]->reg_cache_infos.needed_registers[reg] = NULL; state->free_since[reg]++; } } state->last_access[reg] = state->dst; state->reg_content[reg] = addr; state->dirty[reg] = 0; state->is64bits[reg] = 1; if (addr != NULL) { if (addr == state->r0) xor_reg64_reg64(state, reg, reg); else mov_xreg64_m64rel(state, reg, addr); } return reg; }
void genc_sf_s(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[118]); #endif #ifdef INTERPRET_C_SF_S gencallinterp((unsigned long long)cached_interpreter_table.C_SF_S, 0); #else gencheck_cop1_unusable(); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.ft])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); fcomip_fpreg(1); ffree_fpreg(0); and_m32rel_imm32((unsigned int*)&FCR31, ~0x800000); #endif }
void gencvt_w_s(void) { #ifdef INTERPRET_CVT_W_S gencallinterp((native_type)cached_interpreter_table.CVT_W_S, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fd])); fistp_preg64_dword(RAX); #else mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fs])); fld_preg32_dword(EAX); mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fd])); fistp_preg32_dword(EAX); #endif #endif }
void genmov_s(void) { #ifdef INTERPRET_MOV_S gencallinterp((native_type)cached_interpreter_table.MOV_S, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); mov_reg32_preg64(EBX, RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fd])); mov_preg64_reg32(RAX, EBX); #else mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fs])); mov_reg32_preg32(EBX, EAX); mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fd])); mov_preg32_reg32(EAX, EBX); #endif #endif }
void genc_ule_s(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[118]); #endif #ifdef INTERPRET_C_ULE_S gencallinterp((unsigned long long)cached_interpreter_table.C_ULE_S, 0); #else gencheck_cop1_unusable(); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.ft])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); fucomip_fpreg(1); ffree_fpreg(0); jp_rj(15); ja_rj(13); or_m32rel_imm32((unsigned int*)&FCR31, 0x800000); // 11 jmp_imm_short(11); // 2 and_m32rel_imm32((unsigned int*)&FCR31, ~0x800000); // 11 #endif }
void genfloor_w_s(void) { #ifdef INTERPRET_FLOOR_W_S gencallinterp((native_type)cached_interpreter_table.FLOOR_W_S, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ fldcw_m16rel((unsigned short*)&floor_mode); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fs])); fld_preg64_dword(RAX); mov_xreg64_m64rel(RAX, (unsigned long long *)(®_cop1_simple[dst->f.cf.fd])); fistp_preg64_dword(RAX); fldcw_m16rel((unsigned short*)&rounding_mode); #else fldcw_m16((unsigned short*)&floor_mode); mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fs])); fld_preg32_dword(EAX); mov_eax_memoffs32((unsigned int *)(®_cop1_simple[dst->f.cf.fd])); fistp_preg32_dword(EAX); fldcw_m16((unsigned short*)&rounding_mode); #endif #endif }
void genmtc1(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[114]); #endif #ifdef INTERPRET_MTC1 gencallinterp((unsigned long long)cached_interpreter_table.MTC1, 0); #else gencheck_cop1_unusable(); mov_xreg32_m32rel(EAX, (unsigned int*)dst->f.r.rt); mov_xreg64_m64rel(RBX, (unsigned long long *)(®_cop1_simple[dst->f.r.nrd])); mov_preg64_reg32(RBX, EAX); #endif }
void genmfc1(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[111]); #endif #ifdef INTERPRET_MFC1 gencallinterp((unsigned long long)cached_interpreter_table.MFC1, 0); #else gencheck_cop1_unusable(); mov_xreg64_m64rel(RAX, (unsigned long long *)(&(r4300_cp1_regs_simple())[g_dev.r4300.recomp.dst->f.r.nrd])); mov_reg32_preg64(EBX, RAX); mov_m32rel_xreg32((unsigned int*)g_dev.r4300.recomp.dst->f.r.rt, EBX); sar_reg32_imm8(EBX, 31); mov_m32rel_xreg32(((unsigned int*)g_dev.r4300.recomp.dst->f.r.rt)+1, EBX); #endif }
void gendmtc1(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[115]); #endif #ifdef INTERPRET_DMTC1 gencallinterp((unsigned long long)cached_interpreter_table.DMTC1, 0); #else gencheck_cop1_unusable(); mov_xreg32_m32rel(EAX, (unsigned int*)g_dev.r4300.recomp.dst->f.r.rt); mov_xreg32_m32rel(EBX, ((unsigned int*)g_dev.r4300.recomp.dst->f.r.rt)+1); mov_xreg64_m64rel(RDX, (unsigned long long *)(&(r4300_cp1_regs_double())[g_dev.r4300.recomp.dst->f.r.nrd])); mov_preg64_reg32(RDX, EAX); mov_preg64pimm32_reg32(RDX, 4, EBX); #endif }
void gendmfc1(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[112]); #endif #ifdef INTERPRET_DMFC1 gencallinterp((unsigned long long)cached_interpreter_table.DMFC1, 0); #else gencheck_cop1_unusable(); mov_xreg64_m64rel(RAX, (unsigned long long *) (®_cop1_double[dst->f.r.nrd])); mov_reg32_preg64(EBX, RAX); mov_reg32_preg64pimm32(ECX, RAX, 4); mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EBX); mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, ECX); #endif }
void genmtc1(void) { #ifdef INTERPRET_MTC1 gencallinterp((native_type)cached_interpreter_table.MTC1, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg32_m32rel(EAX, (unsigned int*)dst->f.r.rt); mov_xreg64_m64rel(RBX, (unsigned long long *)(®_cop1_simple[dst->f.r.nrd])); mov_preg64_reg32(RBX, EAX); #else mov_eax_memoffs32((unsigned int*)dst->f.r.rt); mov_reg32_m32(EBX, (unsigned int*)(®_cop1_simple[dst->f.r.nrd])); mov_preg32_reg32(EBX, EAX); #endif #endif }
void gendmfc1(void) { #ifdef INTERPRET_DMFC1 gencallinterp((native_type)cached_interpreter_table.DMFC1, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg64_m64rel(RAX, (unsigned long long *) (®_cop1_double[dst->f.r.nrd])); mov_reg32_preg64(EBX, RAX); mov_reg32_preg64pimm32(ECX, RAX, 4); mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EBX); mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, ECX); #else mov_eax_memoffs32((unsigned int*)(®_cop1_double[dst->f.r.nrd])); mov_reg32_preg32(EBX, EAX); mov_reg32_preg32pimm32(ECX, EAX, 4); mov_m32_reg32((unsigned int*)dst->f.r.rt, EBX); mov_m32_reg32(((unsigned int*)dst->f.r.rt)+1, ECX); #endif #endif }