void multu1() { mov32_eax_mem(_GPR_D(_rs, 0)); mul_mem(_GPR_D(_rt, 0)); mov32_reg_reg(_ecx, _edx); cdq(); mov32_mem_reg((u32)&g_cpu->m_lo.d[2], _eax); mov32_mem_reg((u32)&g_cpu->m_lo.d[3], _edx); if (_rd != 0) { mov32_mem_reg(_GPR_D(_rd, 0), _eax); mov32_mem_reg(_GPR_D(_rd, 1), _edx); } mov32_reg_reg(_eax, _ecx); cdq(); mov32_mem_reg((u32)&g_cpu->m_hi.d[2], _eax); mov32_mem_reg((u32)&g_cpu->m_hi.d[3], _edx); }
void maddu1() { mov32_eax_mem(_GPR_D(_rs, 0)); mul_mem(_GPR_D(_rt, 0)); mov32_reg_reg(_ecx, _edx); // ここでキャリーが立ったら上位ビットに繰り上がる add32_reg_mem(_eax, (u32)&g_cpu->m_lo.d[2]); cdq(); mov32_mem_reg((u32)&g_cpu->m_lo.d[2], _eax); mov32_mem_reg((u32)&g_cpu->m_lo.d[3], _edx); if (_rd != 0) { mov32_mem_reg(_GPR_D(_rd, 0), _eax); mov32_mem_reg(_GPR_D(_rd, 1), _edx); } mov32_reg_reg(_eax, _ecx); adc32_reg_mem(_eax, (u32)&g_cpu->m_hi.d[2]); cdq(); mov32_mem_reg((u32)&g_cpu->m_hi.d[2], _eax); mov32_mem_reg((u32)&g_cpu->m_hi.d[3], _edx); }
void divu1() { // 整数オーバーフローは発生しないはず enum { _1div, _end }; mov32_reg_mem(_ecx, _GPR_D(_rt, 0)); tst32_reg_reg(_ecx, _ecx); jz(_end); mov32_reg_mem(_eax, _GPR_D(_rs, 0)); xor32_reg_reg(_edx, _edx); div_reg(_ecx); mov32_reg_reg(_ecx, _edx); // 商をloに格納 cdq(); mov32_mem_reg((u32)&g_cpu->m_lo.d[2], _eax); mov32_mem_reg((u32)&g_cpu->m_lo.d[3], _edx); mov32_reg_reg(_eax, _ecx); // 余をhiに格納 cdq(); mov32_mem_reg((u32)&g_cpu->m_hi.d[2], _eax); mov32_mem_reg((u32)&g_cpu->m_hi.d[3], _edx); LABEL_DEF(_end); }
void gendiv() { #ifdef INTERPRET_DIV gencallinterp((unsigned long)DIV, 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) + 1 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 cdq(); // 1 idiv_reg32(rt); // 2 #endif }
void gendiv(usf_state_t * state) { #ifdef INTERPRET_DIV gencallinterp(state, (unsigned int)state->current_instruction_table.DIV, 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) + 1 + 2); mov_reg32_reg32(state, EAX, rs); // 0 or 2 cdq(state); // 1 idiv_reg32(state, 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 *)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) + 1 + 2); mov_reg32_reg32(EAX, rs); // 0 or 2 cdq(); // 1 idiv_reg32(rt); // 2 #endif }
void gendiv(void) { #if defined(COUNT_INSTR) inc_m32abs(&instr_count[73]); #endif #ifdef INTERPRET_DIV gencallinterp((unsigned long long)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 }