Changed the M[FT]P[CS] instruction decoding logic to match results from this test:

https://github.com/unknownbrackets/ps2autotests/blob/master/tests/cpu/ee_cop0/performance.cpp
This commit is contained in:
Pseudonym 2016-06-23 20:57:43 +01:00
parent 1a085788de
commit 36dd50005a
2 changed files with 84 additions and 86 deletions

View File

@ -422,22 +422,20 @@ void MFC0()
break;
case 25:
switch(_Imm_ & 0x3F)
{
case 0: // MFPS [LSB is clear]
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pccr.val;
break;
case 1: // MFPC [LSB is set] - read PCR0
COP0_UpdatePCCR();
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pcr0;
break;
case 3: // MFPC [LSB is set] - read PCR1
COP0_UpdatePCCR();
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pcr1;
break;
}
if (0 == (_Imm_ & 1)) // MFPS, register value ignored
{
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pccr.val;
}
else if (0 == (_Imm_ & 2)) // MFPC 0, only LSB of register matters
{
COP0_UpdatePCCR();
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pcr0;
}
else // MFPC 1
{
COP0_UpdatePCCR();
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)cpuRegs.PERF.n.pcr1;
}
/*Console.WriteLn("MFC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x", params
cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/
break;
@ -481,24 +479,24 @@ void MTC0()
case 25:
/*if(bExecBIOS == FALSE && _Rd_ == 25) Console.WriteLn("MTC0 PCCR = %x PCR0 = %x PCR1 = %x IMM= %x", params
cpuRegs.PERF.n.pccr, cpuRegs.PERF.n.pcr0, cpuRegs.PERF.n.pcr1, _Imm_ & 0x3F);*/
switch(_Imm_ & 0x3F)
if (0 == (_Imm_ & 1)) // MTPS
{
case 0: // MTPS [LSB is clear]
// Updates PCRs and sets the PCCR.
COP0_UpdatePCCR();
cpuRegs.PERF.n.pccr.val = cpuRegs.GPR.r[_Rt_].UL[0];
COP0_DiagnosticPCCR();
break;
case 1: // MTPC [LSB is set] - set PCR0
cpuRegs.PERF.n.pcr0 = cpuRegs.GPR.r[_Rt_].UL[0];
s_iLastPERFCycle[0] = cpuRegs.cycle;
break;
case 3: // MTPC [LSB is set] - set PCR0
cpuRegs.PERF.n.pcr1 = cpuRegs.GPR.r[_Rt_].UL[0];
s_iLastPERFCycle[1] = cpuRegs.cycle;
break;
if (0 != (_Imm_ & 0x3E)) // only effective when the register is 0
break;
// Updates PCRs and sets the PCCR.
COP0_UpdatePCCR();
cpuRegs.PERF.n.pccr.val = cpuRegs.GPR.r[_Rt_].UL[0];
COP0_DiagnosticPCCR();
}
else if (0 == (_Imm_ & 2)) // MTPC 0, only LSB of register matters
{
cpuRegs.PERF.n.pcr0 = cpuRegs.GPR.r[_Rt_].UL[0];
s_iLastPERFCycle[0] = cpuRegs.cycle;
}
else // MTPC 1
{
cpuRegs.PERF.n.pcr1 = cpuRegs.GPR.r[_Rt_].UL[0];
s_iLastPERFCycle[1] = cpuRegs.cycle;
}
break;

View File

@ -162,22 +162,21 @@ void recMFC0()
if( _Rd_ == 25 )
{
switch(_Imm_ & 0x3F)
if (0 == (_Imm_ & 1)) // MFPS, register value ignored
{
case 0:
xMOV(eax, ptr[&cpuRegs.PERF.n.pccr]);
break;
case 1:
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR );
xMOV(eax, ptr[&cpuRegs.PERF.n.pcr0]);
break;
case 3:
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR );
xMOV(eax, ptr[&cpuRegs.PERF.n.pcr1]);
break;
xMOV(eax, ptr[&cpuRegs.PERF.n.pccr]);
}
else if (0 == (_Imm_ & 2)) // MFPC 0, only LSB of register matters
{
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR);
xMOV(eax, ptr[&cpuRegs.PERF.n.pcr0]);
}
else // MFPC 1
{
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR);
xMOV(eax, ptr[&cpuRegs.PERF.n.pcr1]);
}
_deleteEEreg(_Rt_, 0);
xMOV(ptr[&cpuRegs.GPR.r[_Rt_].UL[0]], eax);
@ -217,26 +216,27 @@ void recMTC0()
break;
case 25:
switch(_Imm_ & 0x3F)
if (0 == (_Imm_ & 1)) // MTPS
{
case 0:
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR );
xMOV( ptr32[&cpuRegs.PERF.n.pccr], g_cpuConstRegs[_Rt_].UL[0] );
xFastCall(COP0_DiagnosticPCCR );
break;
case 1:
xMOV(eax, ptr[&cpuRegs.cycle]);
xMOV(ptr32[&cpuRegs.PERF.n.pcr0], g_cpuConstRegs[_Rt_].UL[0]);
xMOV(ptr[&s_iLastPERFCycle[0]], eax);
break;
case 3:
xMOV(eax, ptr[&cpuRegs.cycle]);
xMOV(ptr32[&cpuRegs.PERF.n.pcr1], g_cpuConstRegs[_Rt_].UL[0]);
xMOV(ptr[&s_iLastPERFCycle[1]], eax);
break;
if (0 != (_Imm_ & 0x3E)) // only effective when the register is 0
break;
// Updates PCRs and sets the PCCR.
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR);
xMOV(ptr32[&cpuRegs.PERF.n.pccr], g_cpuConstRegs[_Rt_].UL[0]);
xFastCall(COP0_DiagnosticPCCR);
}
else if (0 == (_Imm_ & 2)) // MTPC 0, only LSB of register matters
{
xMOV(eax, ptr[&cpuRegs.cycle]);
xMOV(ptr32[&cpuRegs.PERF.n.pcr0], g_cpuConstRegs[_Rt_].UL[0]);
xMOV(ptr[&s_iLastPERFCycle[0]], eax);
}
else // MTPC 1
{
xMOV(eax, ptr[&cpuRegs.cycle]);
xMOV(ptr32[&cpuRegs.PERF.n.pcr1], g_cpuConstRegs[_Rt_].UL[0]);
xMOV(ptr[&s_iLastPERFCycle[1]], eax);
}
break;
@ -266,26 +266,26 @@ void recMTC0()
break;
case 25:
switch(_Imm_ & 0x3F)
if (0 == (_Imm_ & 1)) // MTPS
{
case 0:
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR );
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pccr, _Rt_);
xFastCall(COP0_DiagnosticPCCR );
break;
case 1:
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr0, _Rt_);
xMOV(ptr[&s_iLastPERFCycle[0]], ecx);
break;
case 3:
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr1, _Rt_);
xMOV(ptr[&s_iLastPERFCycle[1]], ecx);
break;
if (0 != (_Imm_ & 0x3E)) // only effective when the register is 0
break;
iFlushCall(FLUSH_INTERPRETER);
xFastCall(COP0_UpdatePCCR);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pccr, _Rt_);
xFastCall(COP0_DiagnosticPCCR);
}
else if (0 == (_Imm_ & 2)) // MTPC 0, only LSB of register matters
{
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr0, _Rt_);
xMOV(ptr[&s_iLastPERFCycle[0]], ecx);
}
else // MTPC 1
{
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr1, _Rt_);
xMOV(ptr[&s_iLastPERFCycle[1]], ecx);
}
break;