x86: Move cycle/writeback fields to CPU structs

[SAVEVERSION+] Potentially better locality, keeps everything we're
accessing from the rec together.
This commit is contained in:
Connor McLaughlin 2022-11-19 13:19:28 +10:00 committed by refractionpcsx2
parent ff7053c566
commit fd194124a9
19 changed files with 147 additions and 156 deletions

View File

@ -18,9 +18,6 @@
#include "Common.h"
#include "COP0.h"
u32 s_iLastCOP0Cycle = 0;
u32 s_iLastPERFCycle[2] = { 0, 0 };
// Updates the CPU's mode of operation (either, Kernel, Supervisor, or User modes).
// Currently the different modes are not implemented.
// Given this function is called so much, it's commented out for now. (rama)
@ -127,8 +124,8 @@ __fi void COP0_UpdatePCCR()
// or the counting function is not enabled (CTE)
if (cpuRegs.CP0.n.Status.b.ERL || !cpuRegs.PERF.n.pccr.b.CTE)
{
s_iLastPERFCycle[0] = cpuRegs.cycle;
s_iLastPERFCycle[1] = s_iLastPERFCycle[0];
cpuRegs.lastPERFCycle[0] = cpuRegs.cycle;
cpuRegs.lastPERFCycle[1] = cpuRegs.lastPERFCycle[0];
return;
}
@ -142,13 +139,13 @@ __fi void COP0_UpdatePCCR()
if( PERF_ShouldCountEvent( cpuRegs.PERF.n.pccr.b.Event0 ) )
{
u32 incr = cpuRegs.cycle - s_iLastPERFCycle[0];
u32 incr = cpuRegs.cycle - cpuRegs.lastPERFCycle[0];
if( incr == 0 ) incr++;
// use prev/XOR method for one-time exceptions (but likely less correct)
//u32 prev = cpuRegs.PERF.n.pcr0;
cpuRegs.PERF.n.pcr0 += incr;
s_iLastPERFCycle[0] = cpuRegs.cycle;
cpuRegs.lastPERFCycle[0] = cpuRegs.cycle;
//prev ^= (1UL<<31); // XOR is fun!
//if( (prev & cpuRegs.PERF.n.pcr0) & (1UL<<31) )
@ -193,11 +190,11 @@ __fi void COP0_UpdatePCCR()
if( PERF_ShouldCountEvent( cpuRegs.PERF.n.pccr.b.Event1 ) )
{
u32 incr = cpuRegs.cycle - s_iLastPERFCycle[1];
u32 incr = cpuRegs.cycle - cpuRegs.lastPERFCycle[1];
if( incr == 0 ) incr++;
cpuRegs.PERF.n.pcr1 += incr;
s_iLastPERFCycle[1] = cpuRegs.cycle;
cpuRegs.lastPERFCycle[1] = cpuRegs.cycle;
if( (cpuRegs.PERF.n.pcr1 & 0x80000000))
{
@ -456,10 +453,10 @@ void MFC0()
case 9:
{
u32 incr = cpuRegs.cycle-s_iLastCOP0Cycle;
u32 incr = cpuRegs.cycle - cpuRegs.lastCOP0Cycle;
if( incr == 0 ) incr++;
cpuRegs.CP0.n.Count += incr;
s_iLastCOP0Cycle = cpuRegs.cycle;
cpuRegs.lastCOP0Cycle = cpuRegs.cycle;
if( !_Rt_ ) break;
}
[[fallthrough]];
@ -475,7 +472,7 @@ void MTC0()
switch (_Rd_)
{
case 9:
s_iLastCOP0Cycle = cpuRegs.cycle;
cpuRegs.lastCOP0Cycle = cpuRegs.cycle;
cpuRegs.CP0.r[9] = cpuRegs.GPR.r[_Rt_].UL[0];
break;
@ -506,12 +503,12 @@ void MTC0()
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;
cpuRegs.lastPERFCycle[0] = cpuRegs.cycle;
}
else // MTPC 1
{
cpuRegs.PERF.n.pcr1 = cpuRegs.GPR.r[_Rt_].UL[0];
s_iLastPERFCycle[1] = cpuRegs.cycle;
cpuRegs.lastPERFCycle[1] = cpuRegs.cycle;
}
break;

View File

@ -29,8 +29,8 @@ static __fi void IntCHackCheck()
{
// Sanity check: To protect from accidentally "rewinding" the cyclecount
// on the few times nextBranchCycle can be behind our current cycle.
s32 diff = g_nextEventCycle - cpuRegs.cycle;
if (diff > 0 && (cpuRegs.cycle - g_lastEventCycle) > 8) cpuRegs.cycle = g_nextEventCycle;
s32 diff = cpuRegs.nextEventCycle - cpuRegs.cycle;
if (diff > 0 && (cpuRegs.cycle - cpuRegs.lastEventCycle) > 8) cpuRegs.cycle = cpuRegs.nextEventCycle;
}
template< uint page > RETURNS_R128 _hwRead128(u32 mem);

View File

@ -433,7 +433,7 @@ void psxRcntUpdate()
{
int i;
g_iopNextEventCycle = psxRegs.cycle + 32;
psxRegs.iopNextEventCycle = psxRegs.cycle + 32;
psxNextCounter = 0x7fffffff;
psxNextsCounter = psxRegs.cycle;

View File

@ -55,10 +55,10 @@ static void psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore)
if (psxCounters[6].CycleT < psxNextCounter)
psxNextCounter = psxCounters[6].CycleT;
if ((g_iopNextEventCycle - psxNextsCounter) > (u32)psxNextCounter)
if ((psxRegs.iopNextEventCycle - psxNextsCounter) > (u32)psxNextCounter)
{
//DevCon.Warning("SPU2async Setting new counter branch, old %x new %x ((%x - %x = %x) > %x delta)", g_iopNextEventCycle, psxNextsCounter + psxNextCounter, g_iopNextEventCycle, psxNextsCounter, (g_iopNextEventCycle - psxNextsCounter), psxNextCounter);
g_iopNextEventCycle = psxNextsCounter + psxNextCounter;
psxRegs.iopNextEventCycle = psxNextsCounter + psxNextCounter;
}
switch (chcr)

View File

@ -37,19 +37,6 @@ R3000Acpu *psxCpu;
u32 g_psxConstRegs[32];
u32 g_psxHasConstReg, g_psxFlushedConstReg;
// Controls when branch tests are performed.
u32 g_iopNextEventCycle = 0;
// This value is used when the IOP execution is broken to return control to the EE.
// (which happens when the IOP throws EE-bound interrupts). It holds the value of
// iopCycleEE (which is set to zero to facilitate the code break), so that the unrun
// cycles can be accounted for later.
s32 iopBreak = 0;
// tracks the IOP's current sync status with the EE. When it dips below zero,
// control is returned to the EE.
s32 iopCycleEE = -1;
// Used to signal to the EE when important actions that need IOP-attention have
// happened (hsyncs, vsyncs, IOP exceptions, etc). IOP runs code whenever this
// is true, even if it's already running ahead a bit.
@ -67,9 +54,9 @@ void psxReset()
psxRegs.CP0.n.Status = 0x10900000; // COP0 enabled | BEV = 1 | TS = 1
psxRegs.CP0.n.PRid = 0x0000001f; // PRevID = Revision ID, same as the IOP R3000A
iopBreak = 0;
iopCycleEE = -1;
g_iopNextEventCycle = psxRegs.cycle + 4;
psxRegs.iopBreak = 0;
psxRegs.iopCycleEE = -1;
psxRegs.iopNextEventCycle = psxRegs.cycle + 4;
psxHwReset();
PSXCLK = 36864000;
@ -123,8 +110,8 @@ __fi void psxSetNextBranch( u32 startCycle, s32 delta )
// typecast the conditional to signed so that things don't blow up
// if startCycle is greater than our next branch cycle.
if( (int)(g_iopNextEventCycle - startCycle) > delta )
g_iopNextEventCycle = startCycle + delta;
if( (int)(psxRegs.iopNextEventCycle - startCycle) > delta )
psxRegs.iopNextEventCycle = startCycle + delta;
}
__fi void psxSetNextBranchDelta( s32 delta )
@ -151,15 +138,15 @@ __fi void PSX_INT( IopEventId n, s32 ecycle )
psxRegs.sCycle[n] = psxRegs.cycle;
psxRegs.eCycle[n] = ecycle;
psxSetNextBranchDelta( ecycle );
psxSetNextBranchDelta(ecycle);
if( iopCycleEE < 0 )
if (psxRegs.iopCycleEE < 0)
{
// The EE called this int, so inform it to branch as needed:
// fixme - this doesn't take into account EE/IOP sync (the IOP may be running
// ahead or behind the EE as per the EEsCycles value)
s32 iopDelta = (g_iopNextEventCycle-psxRegs.cycle)*8;
cpuSetNextEventDelta( iopDelta );
const s32 iopDelta = (psxRegs.iopNextEventCycle - psxRegs.cycle) * 8;
cpuSetNextEventDelta(iopDelta);
}
}
@ -222,16 +209,16 @@ static __fi void _psxTestInterrupts()
__ri void iopEventTest()
{
if( psxTestCycle( psxNextsCounter, psxNextCounter ) )
if (psxTestCycle(psxNextsCounter, psxNextCounter))
{
psxRcntUpdate();
iopEventAction = true;
}
else
{
// start the next branch at the next counter event by default
// the interrupt code below will assign nearer branches if needed.
g_iopNextEventCycle = psxNextsCounter+psxNextCounter;
// start the next branch at the next counter event by default
// the interrupt code below will assign nearer branches if needed.
psxRegs.iopNextEventCycle = psxNextsCounter + psxNextCounter;
}
if (psxRegs.interrupt)
@ -241,9 +228,9 @@ __ri void iopEventTest()
iopEventTestIsActive = false;
}
if( (psxHu32(0x1078) != 0) && ((psxHu32(0x1070) & psxHu32(0x1074)) != 0) )
if ((psxHu32(0x1078) != 0) && ((psxHu32(0x1070) & psxHu32(0x1074)) != 0))
{
if( (psxRegs.CP0.n.Status & 0xFE01) >= 0x401 )
if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401)
{
PSXCPU_LOG("Interrupt: %x %x", psxHu32(0x1070), psxHu32(0x1074));
psxException(0, 0);

View File

@ -108,6 +108,21 @@ struct psxRegisters {
u32 code; /* The instruction */
u32 cycle;
u32 interrupt;
u32 pcWriteback;
// Controls when branch tests are performed.
u32 iopNextEventCycle;
// This value is used when the IOP execution is broken to return control to the EE.
// (which happens when the IOP throws EE-bound interrupts). It holds the value of
// iopCycleEE (which is set to zero to facilitate the code break), so that the unrun
// cycles can be accounted for later.
s32 iopBreak;
// tracks the IOP's current sync status with the EE. When it dips below zero,
// control is returned to the EE.
s32 iopCycleEE;
u32 sCycle[32]; // start cycle for signaled ints
s32 eCycle[32]; // cycle delta for signaled ints (sCycle + eCycle == branch cycle)
//u32 _msflag[32];
@ -116,10 +131,6 @@ struct psxRegisters {
alignas(16) extern psxRegisters psxRegs;
extern u32 g_iopNextEventCycle;
extern s32 iopBreak; // used when the IOP execution is broken and control returned to the EE
extern s32 iopCycleEE; // tracks IOP's current sych status with the EE
#ifndef _PC_
#define _i32(x) (s32)x //R3000A

View File

@ -243,11 +243,11 @@ static __fi void execI()
if ((psxHu32(HW_ICFG) & (1 << 3)))
{
//One of the Iop to EE delta clocks to be set in PS1 mode.
iopCycleEE-=9;
psxRegs.iopCycleEE -= 9;
}
else
{ //default ps2 mode value
iopCycleEE-=8;
psxRegs.iopCycleEE -= 8;
}
psxBSC[psxRegs.code >> 26]();
}
@ -278,12 +278,12 @@ static void intReset() {
static s32 intExecuteBlock( s32 eeCycles )
{
iopBreak = 0;
iopCycleEE = eeCycles;
psxRegs.iopBreak = 0;
psxRegs.iopCycleEE = eeCycles;
try
{
while (iopCycleEE > 0) {
while (psxRegs.iopCycleEE > 0) {
if ((psxHu32(HW_ICFG) & 8) && ((psxRegs.pc & 0x1fffffffU) == 0xa0 || (psxRegs.pc & 0x1fffffffU) == 0xb0 || (psxRegs.pc & 0x1fffffffU) == 0xc0))
psxBiosCall();
@ -299,7 +299,7 @@ static s32 intExecuteBlock( s32 eeCycles )
Cpu->ExitExecution();
}
return iopBreak + iopCycleEE;
return psxRegs.iopBreak + psxRegs.iopCycleEE;
}
static void intClear(u32 Addr, u32 Size) {

View File

@ -98,7 +98,7 @@ void cpuReset()
fpuRegs.fprc[0] = 0x00002e30; // fpu Revision..
fpuRegs.fprc[31] = 0x01000001; // fpu Status/Control
g_nextEventCycle = cpuRegs.cycle + 4;
cpuRegs.nextEventCycle = cpuRegs.cycle + 4;
EEsCycle = 0;
EEoCycle = cpuRegs.cycle;
@ -237,9 +237,9 @@ __fi void cpuSetNextEvent( u32 startCycle, s32 delta )
// typecast the conditional to signed so that things don't blow up
// if startCycle is greater than our next branch cycle.
if( (int)(g_nextEventCycle - startCycle) > delta )
if( (int)(cpuRegs.nextEventCycle - startCycle) > delta )
{
g_nextEventCycle = startCycle + delta;
cpuRegs.nextEventCycle = startCycle + delta;
}
}
@ -274,7 +274,7 @@ __fi int cpuTestCycle( u32 startCycle, s32 delta )
// tells the EE to run the branch test the next time it gets a chance.
__fi void cpuSetEvent()
{
g_nextEventCycle = cpuRegs.cycle;
cpuRegs.nextEventCycle = cpuRegs.cycle;
}
__fi void cpuClearInt( uint i )
@ -346,8 +346,8 @@ static __fi bool _cpuTestInterrupts()
static __fi void _cpuTestTIMR()
{
cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle;
s_iLastCOP0Cycle = cpuRegs.cycle;
cpuRegs.CP0.n.Count += cpuRegs.cycle - cpuRegs.lastCOP0Cycle;
cpuRegs.lastCOP0Cycle = cpuRegs.cycle;
// fixme: this looks like a hack to make up for the fact that the TIMR
// doesn't yet have a proper mechanism for setting itself up on a nextEventCycle.
@ -385,23 +385,21 @@ static bool cpuIntsEnabled(int Interrupt)
!cpuRegs.CP0.n.Status.b.EXL && (cpuRegs.CP0.n.Status.b.ERL == 0);
}
// if cpuRegs.cycle is greater than this cycle, should check cpuEventTest for updates
u32 g_nextEventCycle = 0;
u32 g_lastEventCycle = 0;
// Shared portion of the branch test, called from both the Interpreter
// and the recompiler. (moved here to help alleviate redundant code)
__fi void _cpuEventTest_Shared()
{
eeEventTestIsActive = true;
g_nextEventCycle = cpuRegs.cycle + eeWaitCycles;
g_lastEventCycle = cpuRegs.cycle;
cpuRegs.nextEventCycle = cpuRegs.cycle + eeWaitCycles;
cpuRegs.lastEventCycle = cpuRegs.cycle;
// ---- INTC / DMAC (CPU-level Exceptions) -----------------
// Done first because exceptions raised during event tests need to be postponed a few
// cycles (fixes Grandia II [PAL], which does a spin loop on a vsync and expects to
// be able to read the value before the exception handler clears it).
uint mask = intcInterrupt() | dmacInterrupt();
if (cpuIntsEnabled(mask)) cpuException(mask, cpuRegs.branch);
if (cpuIntsEnabled(mask))
cpuException(mask, cpuRegs.branch);
// ---- Counters -------------
@ -409,7 +407,7 @@ __fi void _cpuEventTest_Shared()
// escape/suspend hooks, and it's really a good idea to suspend/resume emulation before
// doing any actual meaningful branchtest logic.
if ( cpuTestCycle( nextsCounter, nextCounter ) )
if (cpuTestCycle(nextsCounter, nextCounter))
{
rcntUpdate();
_cpuTestPERF();
@ -429,7 +427,7 @@ __fi void _cpuEventTest_Shared()
// Only use the lower 17 bits of the cpuRegs.interrupt as the upper bits are for VU0/1 sync which can't be done in a tight loop
if ((!g_GameStarted || CHECK_INSTANTDMAHACK) && dmacRegs.ctrl.DMAE && !(psHu8(DMAC_ENABLER + 2) & 1) && (cpuRegs.interrupt & 0x1FFFF))
{
while((cpuRegs.interrupt & 0x1FFFF) && _cpuTestInterrupts())
while ((cpuRegs.interrupt & 0x1FFFF) && _cpuTestInterrupts())
;
}
else
@ -447,17 +445,17 @@ __fi void _cpuEventTest_Shared()
EEsCycle += cpuRegs.cycle - EEoCycle;
EEoCycle = cpuRegs.cycle;
if( EEsCycle > 0 )
if (EEsCycle > 0)
iopEventAction = true;
iopEventTest();
if( iopEventAction )
if (iopEventAction)
{
//if( EEsCycle < -450 )
// Console.WriteLn( " IOP ahead by: %d cycles", -EEsCycle );
EEsCycle = psxCpu->ExecuteBlock( EEsCycle );
EEsCycle = psxCpu->ExecuteBlock(EEsCycle);
iopEventAction = false;
}
@ -470,24 +468,24 @@ __fi void _cpuEventTest_Shared()
// ---- Schedule Next Event Test --------------
if( EEsCycle > 192 )
if (EEsCycle > 192)
{
// EE's running way ahead of the IOP still, so we should branch quickly to give the
// IOP extra timeslices in short order.
cpuSetNextEventDelta( 48 );
cpuSetNextEventDelta(48);
//Console.Warning( "EE ahead of the IOP -- Rapid Event! %d", EEsCycle );
}
// The IOP could be running ahead/behind of us, so adjust the iop's next branch by its
// relative position to the EE (via EEsCycle)
cpuSetNextEventDelta( ((g_iopNextEventCycle-psxRegs.cycle)*8) - EEsCycle );
cpuSetNextEventDelta(((psxRegs.iopNextEventCycle - psxRegs.cycle) * 8) - EEsCycle);
// Apply the hsync counter's nextCycle
cpuSetNextEvent( hsyncCounter.sCycle, hsyncCounter.CycleT );
cpuSetNextEvent(hsyncCounter.sCycle, hsyncCounter.CycleT);
// Apply vsync and other counter nextCycles
cpuSetNextEvent( nextsCounter, nextCounter );
cpuSetNextEvent(nextsCounter, nextCounter);
eeEventTestIsActive = false;
}
@ -496,15 +494,17 @@ __ri void cpuTestINTCInts()
{
// Check the COP0's Status register for general interrupt disables, and the 0x400
// bit (which is INTC master toggle).
if( !cpuIntsEnabled(0x400) ) return;
if (!cpuIntsEnabled(0x400))
return;
if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return;
if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0)
return;
cpuSetNextEventDelta( 4 );
if(eeEventTestIsActive && (iopCycleEE > 0))
cpuSetNextEventDelta(4);
if (eeEventTestIsActive && (psxRegs.iopCycleEE > 0))
{
iopBreak += iopCycleEE; // record the number of cycles the IOP didn't run.
iopCycleEE = 0;
psxRegs.iopBreak += psxRegs.iopCycleEE; // record the number of cycles the IOP didn't run.
psxRegs.iopCycleEE = 0;
}
}
@ -512,27 +512,32 @@ __fi void cpuTestDMACInts()
{
// Check the COP0's Status register for general interrupt disables, and the 0x800
// bit (which is the DMAC master toggle).
if( !cpuIntsEnabled(0x800) ) return;
if (!cpuIntsEnabled(0x800))
return;
if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) &&
( (psHu16(0xe010) & 0x8000) == 0) ) return;
if (((psHu16(0xe012) & psHu16(0xe010)) == 0) &&
((psHu16(0xe010) & 0x8000) == 0))
return;
cpuSetNextEventDelta( 4 );
if(eeEventTestIsActive && (iopCycleEE > 0))
cpuSetNextEventDelta(4);
if (eeEventTestIsActive && (psxRegs.iopCycleEE > 0))
{
iopBreak += iopCycleEE; // record the number of cycles the IOP didn't run.
iopCycleEE = 0;
psxRegs.iopBreak += psxRegs.iopCycleEE; // record the number of cycles the IOP didn't run.
psxRegs.iopCycleEE = 0;
}
}
__fi void cpuTestTIMRInts() {
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {
__fi void cpuTestTIMRInts()
{
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)
{
_cpuTestPERF();
_cpuTestTIMR();
}
}
__fi void cpuTestHwInts() {
__fi void cpuTestHwInts()
{
cpuTestINTCInts();
cpuTestDMACInts();
cpuTestTIMRInts();
@ -551,24 +556,25 @@ __fi void CPU_INT( EE_EventType n, s32 ecycle)
// EE events happen 8 cycles in the future instead of whatever was requested.
// This can be used on games with PATH3 masking issues for example, or when
// some FMV look bad.
if(CHECK_EETIMINGHACK && n < VIF_VU0_FINISH) ecycle = 8;
if (CHECK_EETIMINGHACK && n < VIF_VU0_FINISH)
ecycle = 8;
cpuRegs.interrupt|= 1 << n;
cpuRegs.interrupt |= 1 << n;
cpuRegs.sCycle[n] = cpuRegs.cycle;
cpuRegs.eCycle[n] = ecycle;
// Interrupt is happening soon: make sure both EE and IOP are aware.
if( ecycle <= 28 && iopCycleEE > 0 )
if (ecycle <= 28 && psxRegs.iopCycleEE > 0)
{
// If running in the IOP, force it to break immediately into the EE.
// the EE's branch test is due to run.
iopBreak += iopCycleEE; // record the number of cycles the IOP didn't run.
iopCycleEE = 0;
psxRegs.iopBreak += psxRegs.iopCycleEE; // record the number of cycles the IOP didn't run.
psxRegs.iopCycleEE = 0;
}
cpuSetNextEventDelta( cpuRegs.eCycle[n] );
cpuSetNextEventDelta(cpuRegs.eCycle[n]);
}
// Called from recompilers; define is mandatory.

View File

@ -175,6 +175,13 @@ struct cpuRegisters {
int opmode; // operating mode
u32 tempcycles;
u32 dmastall;
u32 pcWriteback;
// if cpuRegs.cycle is greater than this cycle, should check cpuEventTest for updates
u32 nextEventCycle;
u32 lastEventCycle;
u32 lastCOP0Cycle;
u32 lastPERFCycle[2];
};
// used for optimization
@ -260,11 +267,7 @@ alignas(16) extern cpuRegisters cpuRegs;
alignas(16) extern fpuRegisters fpuRegs;
alignas(16) extern tlbs tlb[48];
extern u32 g_nextEventCycle;
extern u32 g_lastEventCycle;
extern bool eeEventTestIsActive;
extern u32 s_iLastCOP0Cycle;
extern u32 s_iLastPERFCycle[2];
void intSetBranch();

View File

@ -266,12 +266,6 @@ SaveStateBase& SaveStateBase::FreezeInternals()
FreezeTag( "Cycles" );
Freeze(EEsCycle);
Freeze(EEoCycle);
Freeze(iopCycleEE);
Freeze(iopBreak);
Freeze(g_nextEventCycle);
Freeze(g_iopNextEventCycle);
Freeze(s_iLastCOP0Cycle);
Freeze(s_iLastPERFCycle);
Freeze(nextCounter);
Freeze(nextsCounter);
Freeze(psxNextsCounter);

View File

@ -33,7 +33,7 @@ enum class FreezeAction
// [SAVEVERSION+]
// This informs the auto updater that the users savestates will be invalidated.
static const u32 g_SaveVersion = (0x9A30 << 16) | 0x0000;
static const u32 g_SaveVersion = (0x9A31 << 16) | 0x0000;
// the freezing data between submodules and core
@ -44,8 +44,8 @@ static const u32 g_SaveVersion = (0x9A30 << 16) | 0x0000;
// necessarily portable; we might want to investigate this in the future -- govanify
struct freezeData
{
int size;
u8 *data;
int size;
u8* data;
};
struct SaveStateScreenshotData

View File

@ -146,12 +146,12 @@ void recMFC0()
// This case needs to be handled even if the write-back is ignored (_Rt_ == 0 )
xMOV(ecx, ptr[&cpuRegs.cycle]);
xMOV(eax, ecx);
xSUB(eax, ptr[&s_iLastCOP0Cycle]);
xSUB(eax, ptr[&cpuRegs.lastCOP0Cycle]);
u8* skipInc = JNZ8(0);
xINC(eax);
x86SetJ8(skipInc);
xADD(ptr[&cpuRegs.CP0.n.Count], eax);
xMOV(ptr[&s_iLastCOP0Cycle], ecx);
xMOV(ptr[&cpuRegs.lastCOP0Cycle], ecx);
xMOV(eax, ptr[&cpuRegs.CP0.r[_Rd_]]);
if (!_Rt_)
@ -217,7 +217,7 @@ void recMTC0()
case 9:
xMOV(ecx, ptr[&cpuRegs.cycle]);
xMOV(ptr[&s_iLastCOP0Cycle], ecx);
xMOV(ptr[&cpuRegs.lastCOP0Cycle], ecx);
xMOV(ptr32[&cpuRegs.CP0.r[9]], g_cpuConstRegs[_Rt_].UL[0]);
break;
@ -236,13 +236,13 @@ void recMTC0()
{
xMOV(eax, ptr[&cpuRegs.cycle]);
xMOV(ptr32[&cpuRegs.PERF.n.pcr0], g_cpuConstRegs[_Rt_].UL[0]);
xMOV(ptr[&s_iLastPERFCycle[0]], eax);
xMOV(ptr[&cpuRegs.lastPERFCycle[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);
xMOV(ptr[&cpuRegs.lastPERFCycle[1]], eax);
}
break;
@ -274,7 +274,7 @@ void recMTC0()
case 9:
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.CP0.r[9], _Rt_);
xMOV(ptr[&s_iLastCOP0Cycle], ecx);
xMOV(ptr[&cpuRegs.lastCOP0Cycle], ecx);
break;
case 25:
@ -291,13 +291,13 @@ void recMTC0()
{
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr0, _Rt_);
xMOV(ptr[&s_iLastPERFCycle[0]], ecx);
xMOV(ptr[&cpuRegs.lastPERFCycle[0]], ecx);
}
else // MTPC 1
{
xMOV(ecx, ptr[&cpuRegs.cycle]);
_eeMoveGPRtoM((uptr)&cpuRegs.PERF.n.pcr1, _Rt_);
xMOV(ptr[&s_iLastPERFCycle[1]], ecx);
xMOV(ptr[&cpuRegs.lastPERFCycle[1]], ecx);
}
break;

View File

@ -32,10 +32,6 @@ u16 g_xmmAllocCounter = 0;
EEINST* g_pCurInstInfo = NULL;
// used to make sure regs don't get changed while in recompiler
// use FreezeXMMRegs
u32 g_recWriteback = 0;
_xmmregs xmmregs[iREGCNT_XMM], s_saveXMMregs[iREGCNT_XMM];
// X86 caching

View File

@ -91,7 +91,7 @@
#define X86TYPE_VUPWRITE 8
#define X86TYPE_PSX 9
#define X86TYPE_PCWRITEBACK 10
#define X86TYPE_VUJUMP 12 // jump from random mem (g_recWriteback)
#define X86TYPE_PSX_PCWRITEBACK 12
#define X86TYPE_VITEMP 13
#define X86TYPE_FNARG 14 // function parameter, max is 4
@ -253,8 +253,6 @@ static __fi bool EEINST_ISLIVE2(u32 reg) { return !!(g_pCurInstInfo->regs[reg]
static __fi bool FPUINST_ISLIVE(u32 reg) { return !!(g_pCurInstInfo->fpuregs[reg] & EEINST_LIVE0); }
static __fi bool FPUINST_LASTUSE(u32 reg) { return !!(g_pCurInstInfo->fpuregs[reg] & EEINST_LASTUSE); }
extern u32 g_recWriteback; // used for jumps (VUrec mess!)
extern _xmmregs xmmregs[iREGCNT_XMM], s_saveXMMregs[iREGCNT_XMM];
extern thread_local u8* j8Ptr[32]; // depreciated item. use local u8* vars instead.

View File

@ -53,7 +53,6 @@
using namespace x86Emitter;
extern u32 g_iopNextEventCycle;
extern void psxBREAK();
u32 g_psxMaxRecMem = 0;
@ -817,8 +816,8 @@ static void iopClearRecLUT(BASEBLOCK* base, int count)
static __noinline s32 recExecuteBlock(s32 eeCycles)
{
iopBreak = 0;
iopCycleEE = eeCycles;
psxRegs.iopBreak = 0;
psxRegs.iopCycleEE = eeCycles;
#ifdef PCSX2_DEVBUILD
//if (SysTrace.SIF.IsActive())
@ -843,7 +842,7 @@ static __noinline s32 recExecuteBlock(s32 eeCycles)
iopEnterRecompiledCode();
return iopBreak + iopCycleEE;
return psxRegs.iopBreak + psxRegs.iopCycleEE;
}
// Returns the offset to the next instruction after any cleared memory
@ -917,14 +916,14 @@ void psxSetBranchReg(u32 reg)
if (reg != 0xffffffff)
{
_allocX86reg(calleeSavedReg2d, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_allocX86reg(calleeSavedReg2d, X86TYPE_PSX_PCWRITEBACK, 0, MODE_WRITE);
_psxMoveGPRtoR(calleeSavedReg2d, reg);
psxRecompileNextInstruction(1);
if (x86regs[calleeSavedReg2d.GetId()].inuse)
{
pxAssert(x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PCWRITEBACK);
pxAssert(x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PSX_PCWRITEBACK);
xMOV(ptr32[&psxRegs.pc], calleeSavedReg2d);
x86regs[calleeSavedReg2d.GetId()].inuse = 0;
#ifdef PCSX2_DEBUG
@ -933,7 +932,7 @@ void psxSetBranchReg(u32 reg)
}
else
{
xMOV(eax, ptr32[&g_recWriteback]);
xMOV(eax, ptr32[&psxRegs.pcWriteback]);
xMOV(ptr32[&psxRegs.pc], eax);
#ifdef PCSX2_DEBUG
@ -980,16 +979,16 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch)
{
xMOV(eax, ptr32[&psxRegs.cycle]);
xMOV(ecx, eax);
xMOV(edx, ptr32[&iopCycleEE]);
xMOV(edx, ptr32[&psxRegs.iopCycleEE]);
xADD(edx, 7);
xSHR(edx, 3);
xADD(eax, edx);
xCMP(eax, ptr32[&g_iopNextEventCycle]);
xCMOVNS(eax, ptr32[&g_iopNextEventCycle]);
xCMP(eax, ptr32[&psxRegs.iopNextEventCycle]);
xCMOVNS(eax, ptr32[&psxRegs.iopNextEventCycle]);
xMOV(ptr32[&psxRegs.cycle], eax);
xSUB(eax, ecx);
xSHL(eax, 3);
xSUB(ptr32[&iopCycleEE], eax);
xSUB(ptr32[&psxRegs.iopCycleEE], eax);
xJLE(iopExitRecompiledCode);
xFastCall((void*)iopEventTest);
@ -1007,11 +1006,11 @@ static void iPsxBranchTest(u32 newpc, u32 cpuBranch)
xMOV(ptr32[&psxRegs.cycle], eax); // update cycles
// jump if iopCycleEE <= 0 (iop's timeslice timed out, so time to return control to the EE)
xSUB(ptr32[&iopCycleEE], blockCycles * 8);
xSUB(ptr32[&psxRegs.iopCycleEE], blockCycles * 8);
xJLE(iopExitRecompiledCode);
// check if an event is pending
xSUB(eax, ptr32[&g_iopNextEventCycle]);
xSUB(eax, ptr32[&psxRegs.iopNextEventCycle]);
xForwardJS<u8> nointerruptpending;
xFastCall((void*)iopEventTest);
@ -1058,7 +1057,7 @@ void rpsxSYSCALL()
j8Ptr[0] = JE8(0);
xADD(ptr32[&psxRegs.cycle], psxScaleBlockCycles());
xSUB(ptr32[&iopCycleEE], psxScaleBlockCycles() * 8);
xSUB(ptr32[&psxRegs.iopCycleEE], psxScaleBlockCycles() * 8);
JMP32((uptr)iopDispatcherReg - ((uptr)x86Ptr + 5));
// jump target for skipping blockCycle updates
@ -1080,7 +1079,7 @@ void rpsxBREAK()
xCMP(ptr32[&psxRegs.pc], psxpc - 4);
j8Ptr[0] = JE8(0);
xADD(ptr32[&psxRegs.cycle], psxScaleBlockCycles());
xSUB(ptr32[&iopCycleEE], psxScaleBlockCycles() * 8);
xSUB(ptr32[&psxRegs.iopCycleEE], psxScaleBlockCycles() * 8);
JMP32((uptr)iopDispatcherReg - ((uptr)x86Ptr + 5));
x86SetJ8(j8Ptr[0]);
@ -1516,7 +1515,7 @@ StartRecomp:
else
{
xADD(ptr32[&psxRegs.cycle], psxScaleBlockCycles());
xSUB(ptr32[&iopCycleEE], psxScaleBlockCycles() * 8);
xSUB(ptr32[&psxRegs.iopCycleEE], psxScaleBlockCycles() * 8);
}
if (willbranch3 || !psxbranch)

View File

@ -1057,7 +1057,7 @@ void rpsxJR()
void rpsxJALR()
{
// jalr Rs
_allocX86reg(calleeSavedReg2d, X86TYPE_PCWRITEBACK, 0, MODE_WRITE);
_allocX86reg(calleeSavedReg2d, X86TYPE_PSX_PCWRITEBACK, 0, MODE_WRITE);
_psxMoveGPRtoR(calleeSavedReg2d, _Rs_);
if (_Rd_)
@ -1071,7 +1071,7 @@ void rpsxJALR()
if (x86regs[calleeSavedReg2d.GetId()].inuse)
{
pxAssert(x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PCWRITEBACK);
pxAssert(x86regs[calleeSavedReg2d.GetId()].type == X86TYPE_PSX_PCWRITEBACK);
xMOV(ptr32[&psxRegs.pc], calleeSavedReg2d);
x86regs[calleeSavedReg2d.GetId()].inuse = 0;
#ifdef PCSX2_DEBUG
@ -1080,7 +1080,7 @@ void rpsxJALR()
}
else
{
xMOV(eax, ptr32[&g_recWriteback]);
xMOV(eax, ptr32[&psxRegs.pcWriteback]);
xMOV(ptr32[&psxRegs.pc], eax);
#ifdef PCSX2_DEBUG
xOR(eax, eax);

View File

@ -98,11 +98,11 @@ uptr _x86GetAddr(int type, int reg)
break;
case X86TYPE_PCWRITEBACK:
ret = (uptr)&g_recWriteback;
ret = (uptr)&cpuRegs.pcWriteback;
break;
case X86TYPE_VUJUMP:
ret = (uptr)&g_recWriteback;
case X86TYPE_PSX_PCWRITEBACK:
ret = (uptr)&psxRegs.pcWriteback;
break;
jNO_DEFAULT;

View File

@ -363,7 +363,7 @@ void recBranchCall(void (*func)())
// to the current cpu cycle.
xMOV(eax, ptr[&cpuRegs.cycle]);
xMOV(ptr[&g_nextEventCycle], eax);
xMOV(ptr[&cpuRegs.nextEventCycle], eax);
recCall(func);
g_branch = 2;
@ -930,7 +930,7 @@ void SetBranchReg(u32 reg)
}
else
{
xMOV(eax, ptr[&g_recWriteback]);
xMOV(eax, ptr[&cpuRegs.pcWriteback]);
xMOV(ptr[&cpuRegs.pc], eax);
}
}
@ -1125,7 +1125,7 @@ static void iBranchTest(u32 newpc)
if (EmuConfig.Speedhacks.WaitLoop && s_nBlockFF && newpc == s_branchTo)
{
xMOV(eax, ptr32[&g_nextEventCycle]);
xMOV(eax, ptr32[&cpuRegs.nextEventCycle]);
xADD(ptr32[&cpuRegs.cycle], scaleblockcycles());
xCMP(eax, ptr32[&cpuRegs.cycle]);
xCMOVS(eax, ptr32[&cpuRegs.cycle]);
@ -1138,7 +1138,7 @@ static void iBranchTest(u32 newpc)
xMOV(eax, ptr[&cpuRegs.cycle]);
xADD(eax, scaleblockcycles());
xMOV(ptr[&cpuRegs.cycle], eax); // update cycles
xSUB(eax, ptr[&g_nextEventCycle]);
xSUB(eax, ptr[&cpuRegs.nextEventCycle]);
if (newpc == 0xffffffff)
xJS(DispatcherReg);

View File

@ -157,7 +157,7 @@ void recJALR()
}
else
{
xMOV(eax, ptr[&g_recWriteback]);
xMOV(eax, ptr[&cpuRegs.pcWriteback]);
xMOV(ptr[&cpuRegs.pc], eax);
}