static void genbltz_test(void) { int rs_64bit = is64((unsigned int *)dst->f.i.rs); if (!rs_64bit) { int rs = allocate_register((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 } else if (rs_64bit == -1) { cmp_m32_imm32(((unsigned int *)dst->f.i.rs)+1, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 } else { int rs2 = allocate_64_register2((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs2, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 } }
static void genbltz_test(void) { int rs_64bit = is64((unsigned int *)dst->f.i.rs); if (rs_64bit == 0) { #ifdef __x86_64__ int rs = allocate_register_32((unsigned int *)dst->f.i.rs); #else int rs = allocate_register((unsigned int *)dst->f.i.rs); #endif cmp_reg32_imm32(rs, 0); #ifdef __x86_64__ setl_m8rel((unsigned char *) &branch_taken); #else jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 #endif } else if (rs_64bit == -1) { #ifdef __x86_64__ cmp_m32rel_imm32(((unsigned int *)dst->f.i.rs)+1, 0); setl_m8rel((unsigned char *) &branch_taken); #else cmp_m32_imm32(((unsigned int *)dst->f.i.rs)+1, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 #endif } else { #ifdef __x86_64__ int rs = allocate_register_64((uint64_t*)dst->f.i.rs); cmp_reg64_imm8(rs, 0); setl_m8rel((unsigned char *) &branch_taken); #else int rs2 = allocate_64_register2((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs2, 0); jge_rj(12); mov_m32_imm32((unsigned int *)(&branch_taken), 1); // 10 jmp_imm_short(10); // 2 mov_m32_imm32((unsigned int *)(&branch_taken), 0); // 10 #endif } }
void gendivu() { #ifdef INTERPRET_DIVU gencallinterp((unsigned long)DIVU, 0); #else int rs, rt; allocate_register_manually_w(EAX, (unsigned long *)&lo, 0); allocate_register_manually_w(EDX, (unsigned long *)&hi, 0); rs = allocate_register((unsigned long*)dst->f.r.rs); rt = allocate_register((unsigned long*)dst->f.r.rt); cmp_reg32_imm32(rt, 0); je_rj((rs == EAX ? 0 : 2) + 2 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 xor_reg32_reg32(EDX, EDX); // 2 div_reg32(rt); // 2 #endif }
void gendiv(void) { #ifdef INTERPRET_DIV gencallinterp((unsigned int)cached_interpreter_table.DIV, 0); #else int rs, rt; allocate_register_manually_w(EAX, (unsigned int *)&lo, 0); allocate_register_manually_w(EDX, (unsigned int *)&hi, 0); rs = allocate_register((unsigned int*)dst->f.r.rs); rt = allocate_register((unsigned int*)dst->f.r.rt); cmp_reg32_imm32(rt, 0); je_rj((rs == EAX ? 0 : 2) + 1 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 cdq(); // 1 idiv_reg32(rt); // 2 #endif }
void gendivu(usf_state_t * state) { #ifdef INTERPRET_DIVU gencallinterp(state, (unsigned int)state->current_instruction_table.DIVU, 0); #else int rs, rt; allocate_register_manually_w(state, EAX, (unsigned int *)&state->lo, 0); allocate_register_manually_w(state, EDX, (unsigned int *)&state->hi, 0); rs = allocate_register(state, (unsigned int*)state->dst->f.r.rs); rt = allocate_register(state, (unsigned int*)state->dst->f.r.rt); cmp_reg32_imm32(state, rt, 0); je_rj(state, (rs == EAX ? 0 : 2) + 2 + 2); mov_reg32_reg32(state, EAX, rs); // 0 or 2 xor_reg32_reg32(state, EDX, EDX); // 2 div_reg32(state, rt); // 2 #endif }
void gendivu(void) { #ifdef INTERPRET_DIVU gencallinterp((unsigned int)cached_interpreter_table.DIVU, 0); #else int rs, rt; allocate_register_manually_w(EAX, (unsigned int *)r4300_mult_lo(), 0); allocate_register_manually_w(EDX, (unsigned int *)r4300_mult_hi(), 0); rs = allocate_register((unsigned int*)g_dev.r4300.recomp.dst->f.r.rs); rt = allocate_register((unsigned int*)g_dev.r4300.recomp.dst->f.r.rt); cmp_reg32_imm32(rt, 0); je_rj((rs == EAX ? 0 : 2) + 2 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 xor_reg32_reg32(EDX, EDX); // 2 div_reg32(rt); // 2 #endif }
void gendivu(void) { #if defined(COUNT_INSTR) inc_m32abs(&instr_count[74]); #endif #ifdef INTERPRET_DIVU gencallinterp((unsigned long long)DIVU, 0); #else int rs, rt; allocate_register_32_manually_w(EAX, (unsigned int *)&lo); allocate_register_32_manually_w(EDX, (unsigned int *)&hi); rs = allocate_register_32((unsigned int*)dst->f.r.rs); rt = allocate_register_32((unsigned int*)dst->f.r.rt); cmp_reg32_imm32(rt, 0); je_rj((rs == EAX ? 0 : 2) + 2 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 xor_reg32_reg32(EDX, EDX); // 2 div_reg32(rt); // 2 #endif }
void gendiv(void) { #if defined(COUNT_INSTR) inc_m32rel(&instr_count[73]); #endif #ifdef INTERPRET_DIV gencallinterp((unsigned long long)cached_interpreter_table.DIV, 0); #else int rs, rt; allocate_register_32_manually_w(EAX, (unsigned int *)&lo); allocate_register_32_manually_w(EDX, (unsigned int *)&hi); rs = allocate_register_32((unsigned int*)dst->f.r.rs); rt = allocate_register_32((unsigned int*)dst->f.r.rt); cmp_reg32_imm32(rt, 0); je_rj((rs == EAX ? 0 : 2) + 1 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 cdq(); // 1 idiv_reg32(rt); // 2 #endif }
void genbgez_test(void) { int rs_64bit = is64((unsigned int *)dst->f.i.rs); if (rs_64bit == 0) { int rs = allocate_register_32((unsigned int *)dst->f.i.rs); cmp_reg32_imm32(rs, 0); setge_m8rel((unsigned char *) &branch_taken); } else if (rs_64bit == -1) { cmp_m32rel_imm32(((unsigned int *)dst->f.i.rs)+1, 0); setge_m8rel((unsigned char *) &branch_taken); } else { int rs = allocate_register_64((unsigned long long *)dst->f.i.rs); cmp_reg64_imm8(rs, 0); setge_m8rel((unsigned char *) &branch_taken); } }
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(void) { #if defined(COUNT_INSTR) inc_m32abs(&instr_count[62]); #endif #ifdef INTERPRET_JALR gencallinterp((unsigned long long)JALR, 0); #else static unsigned int precomp_instr_size = sizeof(precomp_instr); unsigned int diff = (unsigned int) offsetof(precomp_instr, local_addr); unsigned int diff_need = (unsigned int) offsetof(precomp_instr, reg_cache_infos.need_map); unsigned int diff_wrap = (unsigned int) offsetof(precomp_instr, reg_cache_infos.jump_wrapper); if (((dst->addr & 0xFFF) == 0xFFC && (dst->addr < 0x80000000 || dst->addr >= 0xC0000000))||no_compiled_jump) { gencallinterp((unsigned long long)JALR, 1); return; } free_registers_move_start(); mov_reg32_m32abs(EAX, (unsigned int *)dst->f.r.rs); mov_m32abs_reg32((unsigned int *)&local_rs, EAX); gendelayslot(); mov_m32abs_imm32((unsigned int *)(dst-1)->f.r.rd, dst->addr+4); if ((dst->addr+4) & 0x80000000) mov_m32abs_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0xFFFFFFFF); else mov_m32abs_imm32(((unsigned int *)(dst-1)->f.r.rd)+1, 0); mov_reg32_m32abs(EAX, (unsigned int *)&local_rs); mov_m32abs_reg32((unsigned int *)&last_addr, EAX); gencheck_interupt_reg(); mov_reg32_m32abs(EAX, (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_m32abs_reg32(&jump_to_address, EBX); mov_reg64_imm64(RAX, (unsigned long long) (dst+1)); mov_m64abs_reg64((unsigned long long *)(&PC), RAX); mov_reg64_imm64(RAX, (unsigned long long) jump_to_func); call_reg64(RAX); /* will never return from call */ jump_end_rel32(); mov_reg64_imm64(RSI, (unsigned long long) dst_block->block); mov_reg32_reg32(EAX, EBX); sub_eax_imm32(dst_block->start); shr_reg32_imm8(EAX, 2); mul_m32abs((unsigned int *)(&precomp_instr_size)); mov_reg32_preg64preg64pimm32(EBX, RAX, RSI, diff_need); cmp_reg32_imm32(EBX, 1); jne_rj(11); add_reg32_imm32(EAX, diff_wrap); // 6 add_reg64_reg64(RAX, RSI); // 3 jmp_reg64(RAX); // 2 mov_reg32_preg64preg64pimm32(EBX, RAX, RSI, diff); mov_rax_memoffs64((unsigned long long *) &dst_block->code); add_reg64_reg64(RAX, RBX); jmp_reg64(RAX); #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 }