void force_32(int reg) { if (g_dev.r4300.regcache_state.r64[reg] != -1) { struct precomp_instr *last = g_dev.r4300.regcache_state.last_access[reg]+1; while (last <= g_dev.r4300.recomp.dst) { if (g_dev.r4300.regcache_state.dirty[reg]) last->reg_cache_infos.needed_registers[reg] = g_dev.r4300.regcache_state.reg_content[reg]; else last->reg_cache_infos.needed_registers[reg] = NULL; if (g_dev.r4300.regcache_state.dirty[g_dev.r4300.regcache_state.r64[reg]]) last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]]; else last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = NULL; last++; } if (g_dev.r4300.regcache_state.dirty[reg]) { mov_m32_reg32(g_dev.r4300.regcache_state.reg_content[reg], reg); mov_m32_reg32(g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]], g_dev.r4300.regcache_state.r64[reg]); g_dev.r4300.regcache_state.dirty[reg] = 0; } g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[reg]] = NULL; g_dev.r4300.regcache_state.free_since[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.recomp.dst+1; g_dev.r4300.regcache_state.r64[reg] = -1; } }
void force_32(int reg) { if (r64[reg] != -1) { precomp_instr *last = last_access[reg]+1; while (last <= dst) { if (dirty[reg]) last->reg_cache_infos.needed_registers[reg] = reg_content[reg]; else last->reg_cache_infos.needed_registers[reg] = NULL; if (dirty[r64[reg]]) last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]]; else last->reg_cache_infos.needed_registers[r64[reg]] = NULL; last++; } if (dirty[reg]) { mov_m32_reg32(reg_content[reg], reg); mov_m32_reg32(reg_content[r64[reg]], r64[reg]); dirty[reg] = 0; } last_access[r64[reg]] = NULL; free_since[r64[reg]] = dst+1; r64[reg] = -1; } }
void force_32(usf_state_t * state, int reg) { if (state->r64[reg] != -1) { precomp_instr *last = state->last_access[reg]+1; while (last <= state->dst) { if (state->dirty[reg]) last->reg_cache_infos.needed_registers[reg] = state->reg_content[reg]; else last->reg_cache_infos.needed_registers[reg] = NULL; if (state->dirty[state->r64[reg]]) last->reg_cache_infos.needed_registers[state->r64[reg]] = state->reg_content[state->r64[reg]]; else last->reg_cache_infos.needed_registers[state->r64[reg]] = NULL; last++; } if (state->dirty[reg]) { mov_m32_reg32(state, state->reg_content[reg], reg); mov_m32_reg32(state, state->reg_content[state->r64[reg]], state->r64[reg]); state->dirty[reg] = 0; } state->last_access[state->r64[reg]] = NULL; state->free_since[state->r64[reg]] = state->dst+1; state->r64[reg] = -1; } }
// this function frees a specific X86 GPR void free_register(int reg) { precomp_instr *last; if (last_access[reg] != NULL && r64[reg] != -1 && (int)reg_content[reg] != (int)reg_content[r64[reg]]-4) { free_register(r64[reg]); return; } if (last_access[reg] != NULL) last = last_access[reg]+1; else last = free_since[reg]; while (last <= dst) { if (last_access[reg] != NULL && dirty[reg]) last->reg_cache_infos.needed_registers[reg] = reg_content[reg]; else last->reg_cache_infos.needed_registers[reg] = NULL; if (last_access[reg] != NULL && r64[reg] != -1) { if (dirty[r64[reg]]) last->reg_cache_infos.needed_registers[r64[reg]] = reg_content[r64[reg]]; else last->reg_cache_infos.needed_registers[r64[reg]] = NULL; } last++; } if (last_access[reg] == NULL) { free_since[reg] = dst+1; return; } if (dirty[reg]) { mov_m32_reg32(reg_content[reg], reg); if (r64[reg] == -1) { sar_reg32_imm8(reg, 31); mov_m32_reg32((unsigned int*)reg_content[reg]+1, reg); } else mov_m32_reg32(reg_content[r64[reg]], r64[reg]); } last_access[reg] = NULL; free_since[reg] = dst+1; if (r64[reg] != -1) { last_access[r64[reg]] = NULL; free_since[r64[reg]] = dst+1; } }
// this function frees a specific X86 GPR void free_register(int reg) { struct precomp_instr *last; if (g_dev.r4300.regcache_state.last_access[reg] != NULL && g_dev.r4300.regcache_state.r64[reg] != -1 && (int)g_dev.r4300.regcache_state.reg_content[reg] != (int)g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]]-4) { free_register(g_dev.r4300.regcache_state.r64[reg]); return; } if (g_dev.r4300.regcache_state.last_access[reg] != NULL) last = g_dev.r4300.regcache_state.last_access[reg]+1; else last = g_dev.r4300.regcache_state.free_since[reg]; while (last <= g_dev.r4300.recomp.dst) { if (g_dev.r4300.regcache_state.last_access[reg] != NULL && g_dev.r4300.regcache_state.dirty[reg]) last->reg_cache_infos.needed_registers[reg] = g_dev.r4300.regcache_state.reg_content[reg]; else last->reg_cache_infos.needed_registers[reg] = NULL; if (g_dev.r4300.regcache_state.last_access[reg] != NULL && g_dev.r4300.regcache_state.r64[reg] != -1) { if (g_dev.r4300.regcache_state.dirty[g_dev.r4300.regcache_state.r64[reg]]) last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]]; else last->reg_cache_infos.needed_registers[g_dev.r4300.regcache_state.r64[reg]] = NULL; } last++; } if (g_dev.r4300.regcache_state.last_access[reg] == NULL) { g_dev.r4300.regcache_state.free_since[reg] = g_dev.r4300.recomp.dst+1; return; } if (g_dev.r4300.regcache_state.dirty[reg]) { mov_m32_reg32(g_dev.r4300.regcache_state.reg_content[reg], reg); if (g_dev.r4300.regcache_state.r64[reg] == -1) { sar_reg32_imm8(reg, 31); mov_m32_reg32((unsigned int*)g_dev.r4300.regcache_state.reg_content[reg]+1, reg); } else mov_m32_reg32(g_dev.r4300.regcache_state.reg_content[g_dev.r4300.regcache_state.r64[reg]], g_dev.r4300.regcache_state.r64[reg]); } g_dev.r4300.regcache_state.last_access[reg] = NULL; g_dev.r4300.regcache_state.free_since[reg] = g_dev.r4300.recomp.dst+1; if (g_dev.r4300.regcache_state.r64[reg] != -1) { g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[reg]] = NULL; g_dev.r4300.regcache_state.free_since[g_dev.r4300.regcache_state.r64[reg]] = g_dev.r4300.recomp.dst+1; } }
// this function frees a specific X86 GPR void free_register(usf_state_t * state, int reg) { precomp_instr *last; if (state->last_access[reg] != NULL && state->r64[reg] != -1 && (int)state->reg_content[reg] != (int)state->reg_content[state->r64[reg]]-4) { free_register(state, state->r64[reg]); return; } if (state->last_access[reg] != NULL) last = state->last_access[reg]+1; else last = state->free_since[reg]; while (last <= state->dst) { if (state->last_access[reg] != NULL && state->dirty[reg]) last->reg_cache_infos.needed_registers[reg] = state->reg_content[reg]; else last->reg_cache_infos.needed_registers[reg] = NULL; if (state->last_access[reg] != NULL && state->r64[reg] != -1) { if (state->dirty[state->r64[reg]]) last->reg_cache_infos.needed_registers[state->r64[reg]] = state->reg_content[state->r64[reg]]; else last->reg_cache_infos.needed_registers[state->r64[reg]] = NULL; } last++; } if (state->last_access[reg] == NULL) { state->free_since[reg] = state->dst+1; return; } if (state->dirty[reg]) { mov_m32_reg32(state, state->reg_content[reg], reg); if (state->r64[reg] == -1) { sar_reg32_imm8(state, reg, 31); mov_m32_reg32(state, (unsigned int*)state->reg_content[reg]+1, reg); } else mov_m32_reg32(state, state->reg_content[state->r64[reg]], state->r64[reg]); } state->last_access[reg] = NULL; state->free_since[reg] = state->dst+1; if (state->r64[reg] != -1) { state->last_access[state->r64[reg]] = NULL; state->free_since[state->r64[reg]] = state->dst+1; } }
void gendmfc1(void) { #ifdef INTERPRET_DMFC1 gencallinterp((unsigned int)DMFC1, 0); #else gencheck_cop1_unusable(); 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 }
void genmfc1(void) { #ifdef INTERPRET_MFC1 gencallinterp((unsigned int)MFC1, 0); #else gencheck_cop1_unusable(); mov_eax_memoffs32((unsigned int*)(®_cop1_simple[dst->f.r.nrd])); mov_reg32_preg32(EBX, EAX); mov_m32_reg32((unsigned int*)dst->f.r.rt, EBX); sar_reg32_imm8(EBX, 31); mov_m32_reg32(((unsigned int*)dst->f.r.rt)+1, EBX); #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 }
void gendmultu() { #ifdef INTERPRET_DMULTU gencallinterp((unsigned long)DMULTU, 0); #else free_all_registers(); simplify_access(); mov_eax_memoffs32((unsigned long *)dst->f.r.rs); mul_m32((unsigned long *)dst->f.r.rt); // EDX:EAX = temp1 mov_memoffs32_eax((unsigned long *)(&lo)); mov_reg32_reg32(EBX, EDX); // EBX = temp1>>32 mov_eax_memoffs32((unsigned long *)dst->f.r.rs); mul_m32((unsigned long *)(dst->f.r.rt)+1); add_reg32_reg32(EBX, EAX); adc_reg32_imm32(EDX, 0); mov_reg32_reg32(ECX, EDX); // ECX:EBX = temp2 mov_eax_memoffs32((unsigned long *)(dst->f.r.rs)+1); mul_m32((unsigned long *)dst->f.r.rt); // EDX:EAX = temp3 add_reg32_reg32(EBX, EAX); adc_reg32_imm32(ECX, 0); // ECX:EBX = result2 mov_m32_reg32((unsigned long*)(&lo)+1, EBX); mov_reg32_reg32(ESI, EDX); // ESI = temp3>>32 mov_eax_memoffs32((unsigned long *)(dst->f.r.rs)+1); mul_m32((unsigned long *)(dst->f.r.rt)+1); add_reg32_reg32(EAX, ESI); adc_reg32_imm32(EDX, 0); // EDX:EAX = temp4 add_reg32_reg32(EAX, ECX); adc_reg32_imm32(EDX, 0); // EDX:EAX = result3 mov_memoffs32_eax((unsigned long *)(&hi)); mov_m32_reg32((unsigned long *)(&hi)+1, EDX); #endif }
void gendmultu(usf_state_t * state) { #ifdef INTERPRET_DMULTU gencallinterp(state, (unsigned int)state->current_instruction_table.DMULTU, 0); #else free_all_registers(state); simplify_access(state); mov_eax_memoffs32(state, (unsigned int *)state->dst->f.r.rs); mul_m32(state, (unsigned int *)state->dst->f.r.rt); // EDX:EAX = temp1 mov_memoffs32_eax(state, (unsigned int *)(&state->lo)); mov_reg32_reg32(state, EBX, EDX); // EBX = temp1>>32 mov_eax_memoffs32(state, (unsigned int *)state->dst->f.r.rs); mul_m32(state, (unsigned int *)(state->dst->f.r.rt)+1); add_reg32_reg32(state, EBX, EAX); adc_reg32_imm32(state, EDX, 0); mov_reg32_reg32(state, ECX, EDX); // ECX:EBX = temp2 mov_eax_memoffs32(state, (unsigned int *)(state->dst->f.r.rs)+1); mul_m32(state, (unsigned int *)state->dst->f.r.rt); // EDX:EAX = temp3 add_reg32_reg32(state, EBX, EAX); adc_reg32_imm32(state, ECX, 0); // ECX:EBX = result2 mov_m32_reg32(state, (unsigned int*)(&state->lo)+1, EBX); mov_reg32_reg32(state, EDI, EDX); // EDI = temp3>>32 mov_eax_memoffs32(state, (unsigned int *)(state->dst->f.r.rs)+1); mul_m32(state, (unsigned int *)(state->dst->f.r.rt)+1); add_reg32_reg32(state, EAX, EDI); adc_reg32_imm32(state, EDX, 0); // EDX:EAX = temp4 add_reg32_reg32(state, EAX, ECX); adc_reg32_imm32(state, EDX, 0); // EDX:EAX = result3 mov_memoffs32_eax(state,(unsigned int *)(&state->hi)); mov_m32_reg32(state, (unsigned int *)(&state->hi)+1, EDX); #endif }
void gendmultu(void) { #ifdef INTERPRET_DMULTU gencallinterp((unsigned int)cached_interpreter_table.DMULTU, 0); #else free_all_registers(); simplify_access(); mov_eax_memoffs32((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs); mul_m32((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt); // EDX:EAX = temp1 mov_memoffs32_eax((unsigned int *)(r4300_mult_lo())); mov_reg32_reg32(EBX, EDX); // EBX = temp1>>32 mov_eax_memoffs32((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs); mul_m32((unsigned int *)(g_dev.r4300.recomp.dst->f.r.rt)+1); add_reg32_reg32(EBX, EAX); adc_reg32_imm32(EDX, 0); mov_reg32_reg32(ECX, EDX); // ECX:EBX = temp2 mov_eax_memoffs32((unsigned int *)(g_dev.r4300.recomp.dst->f.r.rs)+1); mul_m32((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt); // EDX:EAX = temp3 add_reg32_reg32(EBX, EAX); adc_reg32_imm32(ECX, 0); // ECX:EBX = result2 mov_m32_reg32((unsigned int*)(r4300_mult_lo())+1, EBX); mov_reg32_reg32(ESI, EDX); // ESI = temp3>>32 mov_eax_memoffs32((unsigned int *)(g_dev.r4300.recomp.dst->f.r.rs)+1); mul_m32((unsigned int *)(g_dev.r4300.recomp.dst->f.r.rt)+1); add_reg32_reg32(EAX, ESI); adc_reg32_imm32(EDX, 0); // EDX:EAX = temp4 add_reg32_reg32(EAX, ECX); adc_reg32_imm32(EDX, 0); // EDX:EAX = result3 mov_memoffs32_eax((unsigned int *)(r4300_mult_hi())); mov_m32_reg32((unsigned int *)(r4300_mult_hi())+1, EDX); #endif }
void genjalr() { #ifdef INTERPRET_JALR gencallinterp((unsigned long)JALR, 0); #else static unsigned long precomp_instr_size = sizeof(precomp_instr); unsigned long diff = (unsigned long)(&dst->local_addr) - (unsigned long)(dst); unsigned long diff_need = (unsigned long)(&dst->reg_cache_infos.need_map) - (unsigned long)(dst); unsigned long diff_wrap = (unsigned long)(&dst->reg_cache_infos.jump_wrapper) - (unsigned long)(dst); unsigned long temp, temp2; if (((dst->addr & 0xFFF) == 0xFFC && (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump) { gencallinterp((unsigned long)JALR, 1); return; } free_all_registers(); simplify_access(); mov_eax_memoffs32((unsigned long *)dst->f.r.rs); mov_memoffs32_eax((unsigned long *)&local_rs); gendelayslot(); mov_m32_imm32((unsigned long *)(dst-1)->f.r.rd, dst->addr+4); if ((dst->addr+4) & 0x80000000) mov_m32_imm32(((unsigned long *)(dst-1)->f.r.rd)+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned long *)(dst-1)->f.r.rd)+1, 0); mov_eax_memoffs32((unsigned long *)&local_rs); mov_memoffs32_eax((unsigned long *)&last_addr); gencheck_interupt_reg(); mov_eax_memoffs32((unsigned long *)&local_rs); mov_reg32_reg32(EBX, EAX); and_eax_imm32(0xFFFFF000); cmp_eax_imm32(dst_block->start & 0xFFFFF000); je_near_rj(0); temp = code_length; mov_m32_reg32(&jump_to_address, EBX); mov_m32_imm32((unsigned long*)(&PC), (unsigned long)(dst+1)); mov_reg32_imm32(EAX, (unsigned long)jump_to_func); call_reg32(EAX); temp2 = code_length; code_length = temp-4; put32(temp2 - temp); code_length = temp2; mov_reg32_reg32(EAX, EBX); sub_eax_imm32(dst_block->start); shr_reg32_imm8(EAX, 2); mul_m32((unsigned long *)(&precomp_instr_size)); mov_reg32_preg32pimm32(EBX, EAX, (unsigned long)(dst_block->block)+diff_need); cmp_reg32_imm32(EBX, 1); jne_rj(7); add_eax_imm32((unsigned long)(dst_block->block)+diff_wrap); // 5 jmp_reg32(EAX); // 2 mov_reg32_preg32pimm32(EAX, EAX, (unsigned long)(dst_block->block)+diff); add_reg32_m32(EAX, (unsigned long *)(&dst_block->code)); jmp_reg32(EAX); #endif }
void genjr(void) { #ifdef INTERPRET_JR gencallinterp((unsigned int)cached_interpreter_table.JR, 1); #else static unsigned int precomp_instr_size = sizeof(precomp_instr); unsigned int diff = (unsigned int)(&dst->local_addr) - (unsigned int)(dst); unsigned int diff_need = (unsigned int)(&dst->reg_cache_infos.need_map) - (unsigned int)(dst); unsigned int diff_wrap = (unsigned int)(&dst->reg_cache_infos.jump_wrapper) - (unsigned int)(dst); if (((dst->addr & 0xFFF) == 0xFFC && (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump) { gencallinterp((unsigned int)cached_interpreter_table.JR, 1); return; } free_all_registers(); simplify_access(); mov_eax_memoffs32((unsigned int *)dst->f.i.rs); mov_memoffs32_eax((unsigned int *)&local_rs); gendelayslot(); mov_eax_memoffs32((unsigned int *)&local_rs); mov_memoffs32_eax((unsigned int *)&last_addr); gencheck_interupt_reg(); mov_eax_memoffs32((unsigned int *)&local_rs); mov_reg32_reg32(EBX, EAX); and_eax_imm32(0xFFFFF000); cmp_eax_imm32(dst_block->start & 0xFFFFF000); je_near_rj(0); jump_start_rel32(); mov_m32_reg32(&jump_to_address, EBX); mov_m32_imm32((unsigned int*)(&PC), (unsigned int)(dst+1)); mov_reg32_imm32(EAX, (unsigned int)jump_to_func); call_reg32(EAX); jump_end_rel32(); mov_reg32_reg32(EAX, EBX); sub_eax_imm32(dst_block->start); shr_reg32_imm8(EAX, 2); mul_m32((unsigned int *)(&precomp_instr_size)); mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(dst_block->block)+diff_need); cmp_reg32_imm32(EBX, 1); jne_rj(7); add_eax_imm32((unsigned int)(dst_block->block)+diff_wrap); // 5 jmp_reg32(EAX); // 2 mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(dst_block->block)+diff); add_reg32_m32(EAX, (unsigned int *)(&dst_block->code)); jmp_reg32(EAX); #endif }
void genjalr(usf_state_t * state) { #ifdef INTERPRET_JALR gencallinterp(state, (unsigned int)state->current_instruction_table.JALR, 0); #else unsigned int diff = (unsigned int)(&state->dst->local_addr) - (unsigned int)(state->dst); unsigned int diff_need = (unsigned int)(&state->dst->reg_cache_infos.need_map) - (unsigned int)(state->dst); unsigned int diff_wrap = (unsigned int)(&state->dst->reg_cache_infos.jump_wrapper) - (unsigned int)(state->dst); if (((state->dst->addr & 0xFFF) == 0xFFC && (state->dst->addr < 0x80000000 || state->dst->addr >= 0xC0000000))||state->no_compiled_jump) { gencallinterp(state, (unsigned int)state->current_instruction_table.JALR, 1); return; } free_all_registers(state); simplify_access(state); mov_eax_memoffs32(state, (unsigned int *)state->dst->f.r.rs); mov_memoffs32_eax(state, (unsigned int *)&state->local_rs); gendelayslot(state); mov_m32_imm32(state, (unsigned int *)(state->dst-1)->f.r.rd, state->dst->addr+4); if ((state->dst->addr+4) & 0x80000000) mov_m32_imm32(state, ((unsigned int *)(state->dst-1)->f.r.rd)+1, 0xFFFFFFFF); else mov_m32_imm32(state, ((unsigned int *)(state->dst-1)->f.r.rd)+1, 0); mov_eax_memoffs32(state, (unsigned int *)&state->local_rs); mov_memoffs32_eax(state, (unsigned int *)&state->last_addr); gencheck_interupt_reg(state); mov_eax_memoffs32(state, (unsigned int *)&state->local_rs); mov_reg32_reg32(state, EBX, EAX); and_eax_imm32(state, 0xFFFFF000); cmp_eax_imm32(state, state->dst_block->start & 0xFFFFF000); je_near_rj(state, 0); jump_start_rel32(state); mov_m32_reg32(state, &state->jump_to_address, EBX); mov_m32_imm32(state, (unsigned int*)(&state->PC), (unsigned int)(state->dst+1)); mov_reg32_imm32(state, EBX, (unsigned int)jump_to_func); mov_reg32_reg32(state, RP0, ESI); call_reg32(state, EBX); jump_end_rel32(state); mov_reg32_reg32(state, EAX, EBX); sub_eax_imm32(state, state->dst_block->start); shr_reg32_imm8(state, EAX, 2); mul_m32(state, (unsigned int *)(&state->precomp_instr_size)); mov_reg32_preg32pimm32(state, EBX, EAX, (unsigned int)(state->dst_block->block)+diff_need); cmp_reg32_imm32(state, EBX, 1); jne_rj(state, 7); add_eax_imm32(state, (unsigned int)(state->dst_block->block)+diff_wrap); // 5 jmp_reg32(state, EAX); // 2 mov_reg32_preg32pimm32(state, EAX, EAX, (unsigned int)(state->dst_block->block)+diff); add_reg32_m32(state, EAX, (unsigned int *)(&state->dst_block->code)); jmp_reg32(state, EAX); #endif }
void genjalr(void) { #ifdef INTERPRET_JALR gencallinterp((unsigned int)cached_interpreter_table.JALR, 0); #else unsigned int diff = (unsigned int)(&g_dev.r4300.recomp.dst->local_addr) - (unsigned int)(g_dev.r4300.recomp.dst); unsigned int diff_need = (unsigned int)(&g_dev.r4300.recomp.dst->reg_cache_infos.need_map) - (unsigned int)(g_dev.r4300.recomp.dst); unsigned int diff_wrap = (unsigned int)(&g_dev.r4300.recomp.dst->reg_cache_infos.jump_wrapper) - (unsigned int)(g_dev.r4300.recomp.dst); if (((g_dev.r4300.recomp.dst->addr & 0xFFF) == 0xFFC && (g_dev.r4300.recomp.dst->addr < 0x80000000 || g_dev.r4300.recomp.dst->addr >= 0xC0000000))||g_dev.r4300.recomp.no_compiled_jump) { gencallinterp((unsigned int)cached_interpreter_table.JALR, 1); return; } free_all_registers(); simplify_access(); mov_eax_memoffs32((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs); mov_memoffs32_eax((unsigned int *)&g_dev.r4300.local_rs); gendelayslot(); mov_m32_imm32((unsigned int *)(g_dev.r4300.recomp.dst-1)->f.r.rd, g_dev.r4300.recomp.dst->addr+4); if ((g_dev.r4300.recomp.dst->addr+4) & 0x80000000) mov_m32_imm32(((unsigned int *)(g_dev.r4300.recomp.dst-1)->f.r.rd)+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned int *)(g_dev.r4300.recomp.dst-1)->f.r.rd)+1, 0); mov_eax_memoffs32((unsigned int *)&g_dev.r4300.local_rs); mov_memoffs32_eax((unsigned int *)&g_dev.r4300.cp0.last_addr); gencheck_interupt_reg(); mov_eax_memoffs32((unsigned int *)&g_dev.r4300.local_rs); mov_reg32_reg32(EBX, EAX); and_eax_imm32(0xFFFFF000); cmp_eax_imm32(g_dev.r4300.recomp.dst_block->start & 0xFFFFF000); je_near_rj(0); jump_start_rel32(); mov_m32_reg32(&g_dev.r4300.cached_interp.jump_to_address, EBX); mov_m32_imm32((unsigned int*)(&(*r4300_pc_struct())), (unsigned int)(g_dev.r4300.recomp.dst+1)); mov_reg32_imm32(EAX, (unsigned int)jump_to_func); call_reg32(EAX); jump_end_rel32(); mov_reg32_reg32(EAX, EBX); sub_eax_imm32(g_dev.r4300.recomp.dst_block->start); shr_reg32_imm8(EAX, 2); mul_m32((unsigned int *)(&precomp_instr_size)); mov_reg32_preg32pimm32(EBX, EAX, (unsigned int)(g_dev.r4300.recomp.dst_block->block)+diff_need); cmp_reg32_imm32(EBX, 1); jne_rj(7); add_eax_imm32((unsigned int)(g_dev.r4300.recomp.dst_block->block)+diff_wrap); // 5 jmp_reg32(EAX); // 2 mov_reg32_preg32pimm32(EAX, EAX, (unsigned int)(g_dev.r4300.recomp.dst_block->block)+diff); add_reg32_m32(EAX, (unsigned int *)(&g_dev.r4300.recomp.dst_block->code)); jmp_reg32(EAX); #endif }