iop: fix division on the interpreter

Recompiler is still completely broken just add tons of FIXME
This commit is contained in:
Gregory Hainaut 2016-01-27 18:15:14 +01:00
parent 41157ee3e9
commit 135cdfca46
2 changed files with 63 additions and 2 deletions

View File

@ -71,14 +71,36 @@ void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd
* Format: OP rs, rt *
*********************************************************/
void psxDIV() {
if (_rRt_ != 0) {
if (_rRt_ == 0) {
// Division by 0
_rLo_ = _i32(_rRs_) < 0 ? 1 : 0xFFFFFFFFu;
_rHi_ = _rRs_;
} else if (_rRs_ == 0x80000000u && _rRt_ == 0xFFFFFFFFu) {
// x86 overflow
_rLo_ = 0x80000000u;
_rHi_ = 0;
} else {
// Normal behavior
_rLo_ = _i32(_rRs_) / _i32(_rRt_);
_rHi_ = _i32(_rRs_) % _i32(_rRt_);
}
}
void psxDIVU() {
if (_rRt_ != 0) {
if (_rRt_ == 0) {
// Division by 0
_rLo_ = 0xFFFFFFFFu;
_rHi_ = _rRs_;
} else if (_rRs_ == 0x80000000u && _rRt_ == 0xFFFFFFFFu) {
// x86 overflow
_rLo_ = 0;
_rHi_ = 0x80000000u;
} else {
// Normal behavior
_rLo_ = _rRs_ / _rRt_;
_rHi_ = _rRs_ % _rRt_;
}

View File

@ -506,11 +506,18 @@ void rpsxDIV_const()
*/
// Of course x86 cpu does overflow !
if (g_psxConstRegs[_Rs_] == 0x80000000u && g_psxConstRegs[_Rt_] == 0xFFFFFFFFu) {
// FIXME depends if div/divu
xMOV(ptr32[&psxRegs.GPR.n.hi], 0);
xMOV(ptr32[&psxRegs.GPR.n.lo], 0x80000000);
return;
}
if (g_psxConstRegs[_Rt_] == 0) {
// FIXME
// hi must be rs
// lo must be 0xFFFF_FFFFF is rs >= 0, 0x1 otherwise if rs < 0 and sign
}
if (g_psxConstRegs[_Rt_] != 0) {
lo = *(int*)&g_psxConstRegs[_Rs_] / *(int*)&g_psxConstRegs[_Rt_];
hi = *(int*)&g_psxConstRegs[_Rs_] % *(int*)&g_psxConstRegs[_Rt_];
@ -523,6 +530,15 @@ void rpsxDIVsuperconsts(int info, int sign)
{
u32 imm = g_psxConstRegs[_Rs_];
if (imm == 0x80000000u) {
// FIXME if RT is 0xFFFFFFFFu
// hi must be 0
// lo must be 0x80000000
// FIXME depends if div/divu
//
// Otherwise standard division
}
if( imm ) {
// Lo/Hi = Rs / Rt (signed)
xMOV(ecx, ptr[&psxRegs.GPR.r[_Rt_]]);
@ -549,6 +565,7 @@ void rpsxDIVsuperconsts(int info, int sign)
xXOR(eax, eax);
xMOV(ptr[&psxRegs.GPR.n.hi], eax);
xMOV(ptr[&psxRegs.GPR.n.lo], eax);
// FIXME lo must be 0xFFFF_FFFFF if rt is 0
}
}
@ -556,6 +573,15 @@ void rpsxDIVsuperconstt(int info, int sign)
{
u32 imm = g_psxConstRegs[_Rt_];
if (imm == 0xFFFFFFFFu) {
// FIXME if RS is 0x80000000
// hi must be 0
// lo must be 0x80000000
// FIXME depends if div/divu
//
// Otherwise standard division
}
if( imm ) {
xMOV(eax, ptr[&psxRegs.GPR.r[_Rs_]]);
xMOV(ecx, imm);
@ -573,6 +599,10 @@ void rpsxDIVsuperconstt(int info, int sign)
xMOV(ptr[&psxRegs.GPR.n.lo], eax);
xMOV(ptr[&psxRegs.GPR.n.hi], edx);
} else {
// FIXME
// hi must be rs
// lo must be 0xFFFF_FFFFF is rs >= 0, 0x1 otherwise if rs < 0 and sign
}
}
@ -596,6 +626,15 @@ void rpsxDIVsuper(int info, int sign)
xMOV(ptr[&psxRegs.GPR.n.lo], eax);
xMOV(ptr[&psxRegs.GPR.n.hi], edx);
x86SetJ8(j8Ptr[0]);
// FIXME if RS is 0x80000000 and RT is 0xFFFF_FFFFF
// hi must be 0
// lo must be 0x80000000
// FIXME depends if div/divu
// FIXME
// hi must be rs
// lo must be 0xFFFF_FFFFF is rs >= 0, 0x1 otherwise
}
void rpsxDIV_consts(int info) { rpsxDIVsuperconsts(info, 1); }