void gensrav(void) { #ifdef INTERPRET_SRAV gencallinterp((unsigned int)cached_interpreter_table.SRAV, 0); #else int rt, rd; allocate_register_manually(ECX, (unsigned int *)dst->f.r.rs); rt = allocate_register((unsigned int *)dst->f.r.rt); rd = allocate_register_w((unsigned int *)dst->f.r.rd); if (rd != ECX) { mov_reg32_reg32(rd, rt); sar_reg32_cl(rd); } else { int temp = lru_register(); free_register(temp); mov_reg32_reg32(temp, rt); sar_reg32_cl(temp); mov_reg32_reg32(rd, temp); } #endif }
static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (!r31_64bit) { int r31 = allocate_register_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); } else if (r31_64bit == -1) { mov_m32_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned int *)®[31])+1, 0); } else { int r311 = allocate_64_register1_w((unsigned int *)®[31]); int r312 = allocate_64_register2_w((unsigned int *)®[31]); mov_reg32_imm32(r311, dst->addr+8); if (dst->addr & 0x80000000) mov_reg32_imm32(r312, 0xFFFFFFFF); else mov_reg32_imm32(r312, 0); } }
void gensllv(usf_state_t * state) { #ifdef INTERPRET_SLLV gencallinterp(state, (unsigned int)state->current_instruction_table.SLLV, 0); #else int rt, rd; allocate_register_manually(state, ECX, (unsigned int *)state->dst->f.r.rs); rt = allocate_register(state, (unsigned int *)state->dst->f.r.rt); rd = allocate_register_w(state, (unsigned int *)state->dst->f.r.rd); if (rd != ECX) { mov_reg32_reg32(state, rd, rt); shl_reg32_cl(state, rd); } else { int temp = lru_register(state); free_register(state, temp); mov_reg32_reg32(state, temp, rt); shl_reg32_cl(state, temp); mov_reg32_reg32(state, rd, temp); } #endif }
void gensllv() { #ifdef INTERPRET_SLLV gencallinterp((unsigned long)SLLV, 0); #else int rt, rd; allocate_register_manually(ECX, (unsigned long *)dst->f.r.rs); rt = allocate_register((unsigned long *)dst->f.r.rt); rd = allocate_register_w((unsigned long *)dst->f.r.rd); if (rd != ECX) { mov_reg32_reg32(rd, rt); shl_reg32_cl(rd); } else { int temp = lru_register(); free_register(temp); mov_reg32_reg32(temp, rt); shl_reg32_cl(temp); mov_reg32_reg32(rd, temp); } #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 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 gensrl(void) { #ifdef INTERPRET_SRL gencallinterp((unsigned int)cached_interpreter_table.SRL, 0); #else int rt = allocate_register((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt); int rd = allocate_register_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd); mov_reg32_reg32(rd, rt); shr_reg32_imm8(rd, g_dev.r4300.recomp.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() { #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(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 }
static void genbranchlink(void) { int r31_64bit = is64((unsigned int*)®[31]); if (r31_64bit == 0) { #ifdef __x86_64__ int r31 = allocate_register_32_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); #else int r31 = allocate_register_w((unsigned int *)®[31]); mov_reg32_imm32(r31, dst->addr+8); #endif } else if (r31_64bit == -1) { #ifdef __x86_64__ mov_m32rel_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32rel_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32rel_imm32(((unsigned int *)®[31])+1, 0); #else mov_m32_imm32((unsigned int *)®[31], dst->addr + 8); if (dst->addr & 0x80000000) mov_m32_imm32(((unsigned int *)®[31])+1, 0xFFFFFFFF); else mov_m32_imm32(((unsigned int *)®[31])+1, 0); #endif } else { #ifdef __x86_64__ int r31 = allocate_register_64_w((uint64_t*)®[31]); mov_reg32_imm32(r31, dst->addr+8); movsxd_reg64_reg32(r31, r31); #else int r311 = allocate_64_register1_w((unsigned int *)®[31]); int r312 = allocate_64_register2_w((unsigned int *)®[31]); mov_reg32_imm32(r311, dst->addr+8); if (dst->addr & 0x80000000) mov_reg32_imm32(r312, 0xFFFFFFFF); else mov_reg32_imm32(r312, 0); #endif } }
void gensltu() { #ifdef INTERPRET_SLTU gencallinterp((unsigned long)SLTU, 0); #else int rs1 = allocate_64_register1((unsigned long *)dst->f.r.rs); int rs2 = allocate_64_register2((unsigned long *)dst->f.r.rs); int rt1 = allocate_64_register1((unsigned long *)dst->f.r.rt); int rt2 = allocate_64_register2((unsigned long *)dst->f.r.rt); int rd = allocate_register_w((unsigned long *)dst->f.r.rd); cmp_reg32_reg32(rs2, rt2); jb_rj(13); jne_rj(4); // 2 cmp_reg32_reg32(rs1, rt1); // 2 jb_rj(7); // 2 mov_reg32_imm32(rd, 0); // 5 jmp_imm_short(5); // 2 mov_reg32_imm32(rd, 1); // 5 #endif }
void genslt(void) { #ifdef INTERPRET_SLT gencallinterp((unsigned int)cached_interpreter_table.SLT, 0); #else int rs1 = allocate_64_register1((unsigned int *)dst->f.r.rs); int rs2 = allocate_64_register2((unsigned int *)dst->f.r.rs); int rt1 = allocate_64_register1((unsigned int *)dst->f.r.rt); int rt2 = allocate_64_register2((unsigned int *)dst->f.r.rt); int rd = allocate_register_w((unsigned int *)dst->f.r.rd); cmp_reg32_reg32(rs2, rt2); jl_rj(13); jne_rj(4); // 2 cmp_reg32_reg32(rs1, rt1); // 2 jl_rj(7); // 2 mov_reg32_imm32(rd, 0); // 5 jmp_imm_short(5); // 2 mov_reg32_imm32(rd, 1); // 5 #endif }
void gensltu(usf_state_t * state) { #ifdef INTERPRET_SLTU gencallinterp(state, (unsigned int)state->current_instruction_table.SLTU, 0); #else int rs1 = allocate_64_register1(state, (unsigned int *)state->dst->f.r.rs); int rs2 = allocate_64_register2(state, (unsigned int *)state->dst->f.r.rs); 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 rd = allocate_register_w(state, (unsigned int *)state->dst->f.r.rd); cmp_reg32_reg32(state, rs2, rt2); jb_rj(state, 13); jne_rj(state, 4); // 2 cmp_reg32_reg32(state, rs1, rt1); // 2 jb_rj(state, 7); // 2 mov_reg32_imm32(state, rd, 0); // 5 jmp_imm_short(state, 5); // 2 mov_reg32_imm32(state, rd, 1); // 5 #endif }
void gensubu() { #ifdef INTERPRET_SUBU gencallinterp((unsigned long)SUBU, 0); #else int rs = allocate_register((unsigned long *)dst->f.r.rs); int rt = allocate_register((unsigned long *)dst->f.r.rt); int rd = allocate_register_w((unsigned long *)dst->f.r.rd); if (rt != rd && rs != rd) { mov_reg32_reg32(rd, rs); sub_reg32_reg32(rd, rt); } else { int temp = lru_register(); free_register(temp); mov_reg32_reg32(temp, rs); sub_reg32_reg32(temp, rt); mov_reg32_reg32(rd, temp); } #endif }
void gensub(void) { #ifdef INTERPRET_SUB gencallinterp((unsigned int)cached_interpreter_table.SUB, 0); #else int rs = allocate_register((unsigned int *)dst->f.r.rs); int rt = allocate_register((unsigned int *)dst->f.r.rt); int rd = allocate_register_w((unsigned int *)dst->f.r.rd); if (rt != rd && rs != rd) { mov_reg32_reg32(rd, rs); sub_reg32_reg32(rd, rt); } else { int temp = lru_register(); free_register(temp); mov_reg32_reg32(temp, rs); sub_reg32_reg32(temp, rt); mov_reg32_reg32(rd, temp); } #endif }
void genaddu(void) { #ifdef INTERPRET_ADDU gencallinterp((unsigned int)cached_interpreter_table.ADDU, 0); #else int rs = allocate_register((unsigned int *)g_dev.r4300.recomp.dst->f.r.rs); int rt = allocate_register((unsigned int *)g_dev.r4300.recomp.dst->f.r.rt); int rd = allocate_register_w((unsigned int *)g_dev.r4300.recomp.dst->f.r.rd); if (rt != rd && rs != rd) { mov_reg32_reg32(rd, rs); add_reg32_reg32(rd, rt); } else { int temp = lru_register(); free_register(temp); mov_reg32_reg32(temp, rs); add_reg32_reg32(temp, rt); mov_reg32_reg32(rd, temp); } #endif }
void gensubu(usf_state_t * state) { #ifdef INTERPRET_SUBU gencallinterp(state, (unsigned int)state->current_instruction_table.SUBU, 0); #else int rs = allocate_register(state, (unsigned int *)state->dst->f.r.rs); 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); if (rt != rd && rs != rd) { mov_reg32_reg32(state, rd, rs); sub_reg32_reg32(state, rd, rt); } else { int temp = lru_register(state); free_register(state, temp); mov_reg32_reg32(state, temp, rs); sub_reg32_reg32(state, temp, rt); mov_reg32_reg32(state, rd, temp); } #endif }
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; }