void gencfc1(void) { #ifdef INTERPRET_CFC1 gencallinterp((native_type)cached_interpreter_table.CFC1, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ if(dst->f.r.nrd == 31) mov_xreg32_m32rel(EAX, (unsigned int*)&FCR31); else mov_xreg32_m32rel(EAX, (unsigned int*)&FCR0); mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EAX); sar_reg32_imm8(EAX, 31); mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, EAX); #else if(dst->f.r.nrd == 31) mov_eax_memoffs32((unsigned int*)&FCR31); else mov_eax_memoffs32((unsigned int*)&FCR0); mov_memoffs32_eax((unsigned int*)dst->f.r.rt); sar_reg32_imm8(EAX, 31); mov_memoffs32_eax(((unsigned int*)dst->f.r.rt)+1); #endif #endif }
void gendsrav(usf_state_t * state) { #ifdef INTERPRET_DSRAV gencallinterp(state, (unsigned int)state->current_instruction_table.DSRAV, 0); #else int rt1, rt2, rd1, rd2; allocate_register_manually(state, ECX, (unsigned int *)state->dst->f.r.rs); rt1 = allocate_64_register1(state, (unsigned int *)state->dst->f.r.rt); rt2 = allocate_64_register2(state, (unsigned int *)state->dst->f.r.rt); rd1 = allocate_64_register1_w(state, (unsigned int *)state->dst->f.r.rd); rd2 = allocate_64_register2_w(state, (unsigned int *)state->dst->f.r.rd); if (rd1 != ECX && rd2 != ECX) { mov_reg32_reg32(state, rd1, rt1); mov_reg32_reg32(state, rd2, rt2); shrd_reg32_reg32_cl(state, rd1,rd2); sar_reg32_cl(state, rd2); test_reg32_imm32(state, ECX, 0x20); je_rj(state, 5); mov_reg32_reg32(state, rd1, rd2); // 2 sar_reg32_imm8(state, rd2, 31); // 3 } else { int temp1, temp2; force_32(state, ECX); temp1 = lru_register(state); temp2 = lru_register_exc1(state, temp1); free_register(state, temp1); free_register(state, temp2); mov_reg32_reg32(state, temp1, rt1); mov_reg32_reg32(state, temp2, rt2); shrd_reg32_reg32_cl(state, temp1, temp2); sar_reg32_cl(state, temp2); test_reg32_imm32(state, ECX, 0x20); je_rj(state, 5); mov_reg32_reg32(state, temp1, temp2); // 2 sar_reg32_imm8(state, temp2, 31); // 3 mov_reg32_reg32(state, rd1, temp1); mov_reg32_reg32(state, rd2, temp2); } #endif }
void gendsrav() { #ifdef INTERPRET_DSRAV gencallinterp((unsigned long)DSRAV, 0); #else int rt1, rt2, rd1, rd2; allocate_register_manually(ECX, (unsigned long *)dst->f.r.rs); rt1 = allocate_64_register1((unsigned long *)dst->f.r.rt); rt2 = allocate_64_register2((unsigned long *)dst->f.r.rt); rd1 = allocate_64_register1_w((unsigned long *)dst->f.r.rd); rd2 = allocate_64_register2_w((unsigned long *)dst->f.r.rd); if (rd1 != ECX && rd2 != ECX) { mov_reg32_reg32(rd1, rt1); mov_reg32_reg32(rd2, rt2); shrd_reg32_reg32_cl(rd1,rd2); sar_reg32_cl(rd2); test_reg32_imm32(ECX, 0x20); je_rj(5); mov_reg32_reg32(rd1, rd2); // 2 sar_reg32_imm8(rd2, 31); // 3 } else { int temp1, temp2; force_32(ECX); temp1 = lru_register(); temp2 = lru_register_exc1(temp1); free_register(temp1); free_register(temp2); mov_reg32_reg32(temp1, rt1); mov_reg32_reg32(temp2, rt2); shrd_reg32_reg32_cl(temp1, temp2); sar_reg32_cl(temp2); test_reg32_imm32(ECX, 0x20); je_rj(5); mov_reg32_reg32(temp1, temp2); // 2 sar_reg32_imm8(temp2, 31); // 3 mov_reg32_reg32(rd1, temp1); mov_reg32_reg32(rd2, temp2); } #endif }
// 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; } }
// 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; } }
void gendsra(usf_state_t * state) { #ifdef INTERPRET_DSRA gencallinterp(state, (unsigned int)state->current_instruction_table.DSRA, 0); #else int rt1 = allocate_64_register1(state, (unsigned int *)state->dst->f.r.rt); int rt2 = allocate_64_register2(state, (unsigned int *)state->dst->f.r.rt); int rd1 = allocate_64_register1_w(state, (unsigned int *)state->dst->f.r.rd); int rd2 = allocate_64_register2_w(state, (unsigned int *)state->dst->f.r.rd); mov_reg32_reg32(state, rd1, rt1); mov_reg32_reg32(state, rd2, rt2); shrd_reg32_reg32_imm8(state, rd1, rd2, state->dst->f.r.sa); sar_reg32_imm8(state, rd2, state->dst->f.r.sa); if (state->dst->f.r.sa & 0x20) { mov_reg32_reg32(state, rd1, rd2); sar_reg32_imm8(state, rd2, 31); } #endif }
void gensra(usf_state_t * state) { #ifdef INTERPRET_SRA gencallinterp(state, (unsigned int)state->current_instruction_table.SRA, 0); #else int rt = allocate_register(state, (unsigned int *)state->dst->f.r.rt); int rd = allocate_register_w(state, (unsigned int *)state->dst->f.r.rd); mov_reg32_reg32(state, rd, rt); sar_reg32_imm8(state, rd, state->dst->f.r.sa); #endif }
void genmfc1(void) { #ifdef INTERPRET_MFC1 gencallinterp((native_type)cached_interpreter_table.MFC1, 0); #else gencheck_cop1_unusable(); #ifdef __x86_64__ mov_xreg64_m64rel(RAX, (unsigned long long*)(®_cop1_simple[dst->f.r.nrd])); mov_reg32_preg64(EBX, RAX); mov_m32rel_xreg32((uint32_t*)dst->f.r.rt, EBX); sar_reg32_imm8(EBX, 31); mov_m32rel_xreg32(((uint32_t*)dst->f.r.rt)+1, EBX); #else 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 #endif }
void gendsra(void) { #ifdef INTERPRET_DSRA gencallinterp((unsigned int)cached_interpreter_table.DSRA, 0); #else int rt1 = allocate_64_register1((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt); int rt2 = allocate_64_register2((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt); int rd1 = allocate_64_register1_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd); int rd2 = allocate_64_register2_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd); mov_reg32_reg32(rd1, rt1); mov_reg32_reg32(rd2, rt2); shrd_reg32_reg32_imm8(rd1, rd2, g_dev.r4300.recomp.dst->f.r.sa); sar_reg32_imm8(rd2, g_dev.r4300.recomp.dst->f.r.sa); if (g_dev.r4300.recomp.dst->f.r.sa & 0x20) { mov_reg32_reg32(rd1, rd2); sar_reg32_imm8(rd2, 31); } #endif }
void gendsra() { #ifdef INTERPRET_DSRA gencallinterp((unsigned long)DSRA, 0); #else int rt1 = allocate_64_register1((unsigned long *)dst->f.r.rt); int rt2 = allocate_64_register2((unsigned long *)dst->f.r.rt); int rd1 = allocate_64_register1_w((unsigned long *)dst->f.r.rd); int rd2 = allocate_64_register2_w((unsigned long *)dst->f.r.rd); mov_reg32_reg32(rd1, rt1); mov_reg32_reg32(rd2, rt2); shrd_reg32_reg32_imm8(rd1, rd2, dst->f.r.sa); sar_reg32_imm8(rd2, dst->f.r.sa); if (dst->f.r.sa & 0x20) { mov_reg32_reg32(rd1, rd2); sar_reg32_imm8(rd2, 31); } #endif }
void gensra() { #ifdef INTERPRET_SRA gencallinterp((unsigned long)SRA, 0); #else int rt = allocate_register((unsigned long *)dst->f.r.rt); int rd = allocate_register_w((unsigned long *)dst->f.r.rd); mov_reg32_reg32(rd, rt); sar_reg32_imm8(rd, dst->f.r.sa); #endif }
void gendsra32() { #ifdef INTERPRET_DSRA32 gencallinterp((unsigned long)DSRA32, 0); #else int rt2 = allocate_64_register2((unsigned long *)dst->f.r.rt); int rd = allocate_register_w((unsigned long *)dst->f.r.rd); mov_reg32_reg32(rd, rt2); sar_reg32_imm8(rd, dst->f.r.sa); #endif }
void gensra(void) { #ifdef INTERPRET_SRA gencallinterp((unsigned int)cached_interpreter_table.SRA, 0); #else int rt = allocate_register((unsigned int *)dst->f.r.rt); int rd = allocate_register_w((unsigned int *)dst->f.r.rd); mov_reg32_reg32(rd, rt); sar_reg32_imm8(rd, dst->f.r.sa); #endif }
void gendsra32(void) { #ifdef INTERPRET_DSRA32 gencallinterp((unsigned int)cached_interpreter_table.DSRA32, 0); #else int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); int rd = allocate_register_w((unsigned int *)dst->f.r.rd); mov_reg32_reg32(rd, rt2); sar_reg32_imm8(rd, dst->f.r.sa); #endif }
void gencfc1(void) { #ifdef INTERPRET_CFC1 gencallinterp((unsigned int)CFC1, 0); #else gencheck_cop1_unusable(); if(dst->f.r.nrd == 31) mov_eax_memoffs32((unsigned int*)&FCR31); else mov_eax_memoffs32((unsigned int*)&FCR0); mov_memoffs32_eax((unsigned int*)dst->f.r.rt); sar_reg32_imm8(EAX, 31); mov_memoffs32_eax(((unsigned int*)dst->f.r.rt)+1); #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 gensra(void) { #if defined(COUNT_INSTR) inc_m32abs(&instr_count[57]); #endif #ifdef INTERPRET_SRA gencallinterp((unsigned long long)SRA, 0); #else int rt = allocate_register_32((unsigned int *)dst->f.r.rt); int rd = allocate_register_32_w((unsigned int *)dst->f.r.rd); mov_reg32_reg32(rd, rt); sar_reg32_imm8(rd, dst->f.r.sa); #endif }
void gencfc1(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[113]); #endif #ifdef INTERPRET_CFC1 gencallinterp((unsigned long long)cached_interpreter_table.CFC1, 0); #else gencheck_cop1_unusable(); if(dst->f.r.nrd == 31) mov_xreg32_m32rel(EAX, (unsigned int*)&FCR31); else mov_xreg32_m32rel(EAX, (unsigned int*)&FCR0); mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EAX); sar_reg32_imm8(EAX, 31); mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, 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 *)(®_cop1_simple[dst->f.r.nrd])); mov_reg32_preg64(EBX, RAX); mov_m32rel_xreg32((unsigned int*)dst->f.r.rt, EBX); sar_reg32_imm8(EBX, 31); mov_m32rel_xreg32(((unsigned int*)dst->f.r.rt)+1, EBX); #endif }
// this function is similar to allocate_register except it loads // a 64 bits value, and return the register number of the MSB part int allocate_64_register2(unsigned int *addr) { int reg1, reg2, i; // is it already cached as a 32 bits value ? for (i=0; i<8; i++) { if (last_access[i] != NULL && reg_content[i] == addr) { if (r64[i] == -1) { allocate_register(addr); reg2 = allocate_register(dirty[i] ? NULL : addr+1); r64[i] = reg2; r64[reg2] = i; if (dirty[i]) { reg_content[reg2] = addr+1; dirty[reg2] = 1; mov_reg32_reg32(reg2, i); sar_reg32_imm8(reg2, 31); } return reg2; } } } reg1 = allocate_register(addr); reg2 = allocate_register(addr+1); r64[reg1] = reg2; r64[reg2] = reg1; return reg2; }
// 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_64_register1(unsigned int *addr) { int reg1, reg2, i; // is it already cached as a 32 bits value ? for (i=0; i<8; i++) { if (g_dev.r4300.regcache_state.last_access[i] != NULL && g_dev.r4300.regcache_state.reg_content[i] == addr) { if (g_dev.r4300.regcache_state.r64[i] == -1) { allocate_register(addr); reg2 = allocate_register(g_dev.r4300.regcache_state.dirty[i] ? NULL : addr+1); g_dev.r4300.regcache_state.r64[i] = reg2; g_dev.r4300.regcache_state.r64[reg2] = i; if (g_dev.r4300.regcache_state.dirty[i]) { g_dev.r4300.regcache_state.reg_content[reg2] = addr+1; g_dev.r4300.regcache_state.dirty[reg2] = 1; mov_reg32_reg32(reg2, i); sar_reg32_imm8(reg2, 31); } return i; } } } reg1 = allocate_register(addr); reg2 = allocate_register(addr+1); g_dev.r4300.regcache_state.r64[reg1] = reg2; g_dev.r4300.regcache_state.r64[reg2] = reg1; return reg1; }
// this function is similar to allocate_register except it loads // a 64 bits value, and return the register number of the MSB part int allocate_64_register2(usf_state_t * state, unsigned int *addr) { int reg1, reg2, i; // is it already cached as a 32 bits value ? for (i=0; i<8; i++) { if (state->last_access[i] != NULL && state->reg_content[i] == addr) { if (state->r64[i] == -1) { allocate_register(state, addr); reg2 = allocate_register(state, state->dirty[i] ? NULL : addr+1); state->r64[i] = reg2; state->r64[reg2] = i; if (state->dirty[i]) { state->reg_content[reg2] = addr+1; state->dirty[reg2] = 1; mov_reg32_reg32(state, reg2, i); sar_reg32_imm8(state, reg2, 31); } return reg2; } } } reg1 = allocate_register(state, addr); reg2 = allocate_register(state, addr+1); state->r64[reg1] = reg2; state->r64[reg2] = reg1; return reg2; }
int allocate_64_register2_w(usf_state_t * state, unsigned int *addr) { int reg1, reg2, i; // is it already cached as a 32 bits value ? for (i=0; i<8; i++) { if (state->last_access[i] != NULL && state->reg_content[i] == addr) { if (state->r64[i] == -1) { allocate_register_w(state, addr); reg2 = lru_register(state); if (state->last_access[reg2]) free_register(state, reg2); else { while (state->free_since[reg2] <= state->dst) { state->free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL; state->free_since[reg2]++; } } state->r64[i] = reg2; state->r64[reg2] = i; state->last_access[reg2] = state->dst; state->reg_content[reg2] = addr+1; state->dirty[reg2] = 1; mov_reg32_reg32(state, reg2, i); sar_reg32_imm8(state, reg2, 31); return reg2; } else { state->last_access[i] = state->dst; state->last_access[state->r64[i]] = state->dst; state->dirty[i] = state->dirty[state->r64[i]] = 1; return state->r64[i]; } } } reg1 = allocate_register_w(state, addr); reg2 = lru_register(state); if (state->last_access[reg2]) free_register(state, reg2); else { while (state->free_since[reg2] <= state->dst) { state->free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL; state->free_since[reg2]++; } } state->r64[reg1] = reg2; state->r64[reg2] = reg1; state->last_access[reg2] = state->dst; state->reg_content[reg2] = addr+1; state->dirty[reg2] = 1; return reg2; }
int allocate_64_register2_w(unsigned int *addr) { int reg1, reg2, i; // is it already cached as a 32 bits value ? for (i=0; i<8; i++) { if (last_access[i] != NULL && reg_content[i] == addr) { if (r64[i] == -1) { allocate_register_w(addr); reg2 = lru_register(); if (last_access[reg2]) free_register(reg2); else { while (free_since[reg2] <= dst) { free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL; free_since[reg2]++; } } r64[i] = reg2; r64[reg2] = i; last_access[reg2] = dst; reg_content[reg2] = addr+1; dirty[reg2] = 1; mov_reg32_reg32(reg2, i); sar_reg32_imm8(reg2, 31); return reg2; } else { last_access[i] = dst; last_access[r64[i]] = dst; dirty[i] = dirty[r64[i]] = 1; return r64[i]; } } } reg1 = allocate_register_w(addr); reg2 = lru_register(); if (last_access[reg2]) free_register(reg2); else { while (free_since[reg2] <= dst) { free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL; free_since[reg2]++; } } r64[reg1] = reg2; r64[reg2] = reg1; last_access[reg2] = dst; reg_content[reg2] = addr+1; dirty[reg2] = 1; return reg2; }
int allocate_64_register2_w(unsigned int *addr) { int reg1, reg2, i; // is it already cached as a 32 bits value ? for (i=0; i<8; i++) { if (g_dev.r4300.regcache_state.last_access[i] != NULL && g_dev.r4300.regcache_state.reg_content[i] == addr) { if (g_dev.r4300.regcache_state.r64[i] == -1) { allocate_register_w(addr); reg2 = lru_register(); if (g_dev.r4300.regcache_state.last_access[reg2]) free_register(reg2); else { while (g_dev.r4300.regcache_state.free_since[reg2] <= g_dev.r4300.recomp.dst) { g_dev.r4300.regcache_state.free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL; g_dev.r4300.regcache_state.free_since[reg2]++; } } g_dev.r4300.regcache_state.r64[i] = reg2; g_dev.r4300.regcache_state.r64[reg2] = i; g_dev.r4300.regcache_state.last_access[reg2] = g_dev.r4300.recomp.dst; g_dev.r4300.regcache_state.reg_content[reg2] = addr+1; g_dev.r4300.regcache_state.dirty[reg2] = 1; mov_reg32_reg32(reg2, i); sar_reg32_imm8(reg2, 31); return reg2; } else { g_dev.r4300.regcache_state.last_access[i] = g_dev.r4300.recomp.dst; g_dev.r4300.regcache_state.last_access[g_dev.r4300.regcache_state.r64[i]] = g_dev.r4300.recomp.dst; g_dev.r4300.regcache_state.dirty[i] = g_dev.r4300.regcache_state.dirty[g_dev.r4300.regcache_state.r64[i]] = 1; return g_dev.r4300.regcache_state.r64[i]; } } } reg1 = allocate_register_w(addr); reg2 = lru_register(); if (g_dev.r4300.regcache_state.last_access[reg2]) free_register(reg2); else { while (g_dev.r4300.regcache_state.free_since[reg2] <= g_dev.r4300.recomp.dst) { g_dev.r4300.regcache_state.free_since[reg2]->reg_cache_infos.needed_registers[reg2] = NULL; g_dev.r4300.regcache_state.free_since[reg2]++; } } g_dev.r4300.regcache_state.r64[reg1] = reg2; g_dev.r4300.regcache_state.r64[reg2] = reg1; g_dev.r4300.regcache_state.last_access[reg2] = g_dev.r4300.recomp.dst; g_dev.r4300.regcache_state.reg_content[reg2] = addr+1; g_dev.r4300.regcache_state.dirty[reg2] = 1; return reg2; }