Applied the IOP counter optimization to the EE counters. Don't expect any noticeable speedups though, since this doesn't really affect the hsync/vsync counters which are the ones that end up doing 90% of the work. (but there's always a chance that it'll favor a game that likes to abuse the counters)

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@280 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2008-11-03 02:31:15 +00:00 committed by Gregory Hainaut
parent f113aab091
commit 1fbeeeb678
5 changed files with 155 additions and 126 deletions

View File

@ -48,23 +48,31 @@ void rcntReset(int index) {
rcntUpd(index);
}
void rcntSet() {
// Updates the state of the nextCounter value (if needed) to serve
// any pending events for the given counter.
// Call this method after any modifications to the state of a counter.
static __forceinline void _rcntSet( int i )
{
u32 c;
if (!(counters[i].mode & 0x80) || (counters[i].mode & 0x3) == 0x3) return; // Stopped
c = ((0x10000 - counters[i].count) * counters[i].rate) - (cpuRegs.cycle - counters[i].sCycleT);
if (c < nextCounter) nextCounter = c;
//if(!(counters[i].mode & 0x100) || counters[i].target > 0xffff) continue;
c = ((counters[i].target - counters[i].count) * counters[i].rate) - (cpuRegs.cycle - counters[i].sCycleT);
if (c < nextCounter) nextCounter = c;
}
static __forceinline void cpuRcntSet() {
int i;
nextCounter = (counters[4].CycleT < counters[5].CycleT) ? counters[4].CycleT : counters[5].CycleT;
nextsCounter = cpuRegs.cycle;
for (i = 0; i < 4; i++) {
if (!(counters[i].mode & 0x80) || (counters[i].mode & 0x3) == 0x3) continue; // Stopped
c = ((0x10000 - counters[i].count) * counters[i].rate) - (cpuRegs.cycle - counters[i].sCycleT);
if (c < nextCounter) nextCounter = c;
//if(!(counters[i].mode & 0x100) || counters[i].target > 0xffff) continue;
c = ((counters[i].target - counters[i].count) * counters[i].rate) - (cpuRegs.cycle - counters[i].sCycleT);
if (c < nextCounter) nextCounter = c;
}
for (i = 0; i < 4; i++)
_rcntSet( i );
}
void rcntInit() {
@ -88,7 +96,7 @@ void rcntInit() {
#endif
for (i=0; i<4; i++) rcntUpd(i);
rcntSet();
cpuRcntSet();
assert(Cpu != NULL && Cpu->ExecuteVU1Block != NULL );
s_prevExecuteVU1Block = Cpu->ExecuteVU1Block;
@ -150,7 +158,7 @@ void UpdateVSyncRate() {
iTicks = (GetTickFrequency() / 5994) * 100;
SysPrintf("Framelimiter rate updated (UpdateVSyncRate): 59.94 fps NTSC\n");
}
rcntSet();
cpuRcntSet();
}
void FrameLimiter()
@ -398,7 +406,7 @@ static __forceinline void hScanline()
if (difference >= HBLANK_TIME_ ) {
hScanlineNextCycle(difference, HBLANK_TIME_);
rcntStartGate(0, counters[4].sCycle);
psxCheckStartGate(0);
psxCheckStartGate16(0);
counters[4].mode = MODE_HRENDER;
}
}
@ -408,13 +416,14 @@ static __forceinline void hScanline()
if (CSRw & 0x4) GSCSRr |= 4; // signal
if (!(GSIMR&0x400)) gsIrq();
if (gates) rcntEndGate(0, counters[4].sCycle);
if (psxhblankgate) psxCheckEndGate(0);
if (psxhblankgate) psxCheckEndGate16(0);
counters[4].mode = MODE_HBLANK;
}
}
}
void vSync()
// Only called from one place so might as well inline it.
static __forceinline void vSync()
{
u32 diff = (cpuRegs.cycle - counters[5].sCycle);
@ -435,7 +444,10 @@ void vSync()
}
}
void rcntUpdate()
// forceinline note: this method is called from two locations, but one
// of them is the interpreter, which doesn't count. ;) So might as
// well forceinline it!
__forceinline void rcntUpdate()
{
int i;
@ -488,7 +500,7 @@ void rcntUpdate()
}
}
rcntSet();
cpuRcntSet();
}
void rcntWcount(int index, u32 value)
@ -506,7 +518,7 @@ void rcntWcount(int index, u32 value)
counters[index].sCycleT = cpuRegs.cycle - change;
}
rcntSet();
_rcntSet( index );
}
void rcntWmode(int index, u32 value)
@ -552,7 +564,7 @@ void rcntWmode(int index, u32 value)
counters[index].target &= 0xffff;
}*/
rcntSet();
_rcntSet( index );
}
void rcntStartGate(unsigned int mode, u32 sCycle) {
@ -584,6 +596,9 @@ void rcntStartGate(unsigned int mode, u32 sCycle) {
break;
}
}
// Note: No need to set counters here.
// They'll get set later on in rcntUpdate, since we're
// being called from there anyway.
}
void rcntEndGate(unsigned int mode, u32 sCycle) {
@ -601,7 +616,7 @@ void rcntEndGate(unsigned int mode, u32 sCycle) {
break;
case 0x10:
counters[i].count = rcntRcount(i);
break;
break; // skip the _rcntSet
case 0x20: //Reset and start counting on Vsync end
case 0x30: //Reset and start counting on Vsync start and end
counters[i].mode |= 0x80;
@ -612,6 +627,9 @@ void rcntEndGate(unsigned int mode, u32 sCycle) {
break;
}
}
// Note: No need to set counters here.
// They'll get set later on in rcntUpdate, since we're
// being called from there anyway.
}
void rcntWtarget(int index, u32 value) {
@ -623,7 +641,7 @@ void rcntWtarget(int index, u32 value) {
//SysPrintf("EE Saving target %d from early trigger, target = %x, count = %x\n", index, counters[index].target, rcntCycle(index));
counters[index].target |= 0x10000000;
}
rcntSet();
_rcntSet( index );
}
void rcntWhold(int index, u32 value) {

View File

@ -92,8 +92,9 @@ typedef struct {
extern Counter counters[6];
extern u32 nextCounter, nextsCounter;
extern void rcntUpdate();
void rcntInit();
void rcntUpdate();
void rcntStartGate(unsigned int mode, u32 sCycle);
void rcntEndGate(unsigned int mode, u32 sCycle);
void rcntWcount(int index, u32 value);

View File

@ -155,127 +155,133 @@ void psxRcntInit() {
void psxVBlankStart() {
cdvdVsync();
psxHu32(0x1070)|= 1;
if(psxvblankgate & 1) psxCheckStartGate(1);
if(psxvblankgate & (1 << 3)) psxCheckStartGate(3);
if(psxvblankgate & 1) psxCheckStartGate16(1);
if(psxvblankgate & (1 << 3)) psxCheckStartGate32(3);
}
void psxVBlankEnd() {
psxHu32(0x1070)|= 0x800;
if(psxvblankgate & 1) psxCheckEndGate(1);
if(psxvblankgate & (1 << 3)) psxCheckEndGate(3);
if(psxvblankgate & 1) psxCheckEndGate16(1);
if(psxvblankgate & (1 << 3)) psxCheckEndGate32(3);
}
void psxCheckEndGate(int counter) { //Check Gate events when Vsync Ends
int i = counter;
void psxCheckEndGate16(int i)
{
//SysPrintf("End Gate %x\n", counter);
if(counter < 3){ //Gates for 16bit counters
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxCounters[i].count += (u16)psxRcntRcount16(i); //Only counts when signal is on
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxCounters[i].mode &= ~0x10000000;
psxRcntUpd16(i);
break;
case 0x3: //GATE_ON_Start
break;
default:
SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n");
break;
}
}
assert(i < 3);
if(counter >= 3){ //Gates for 32bit counters
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxCounters[i].count += (u32)psxRcntRcount32(i); //Only counts when signal is on
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxCounters[i].mode &= ~0x10000000;
psxRcntUpd32(i);
break;
case 0x3: //GATE_ON_Start
break;
default:
SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n");
break;
}
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxCounters[i].count += (u16)psxRcntRcount16(i); //Only counts when signal is on
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxCounters[i].mode &= ~0x10000000;
psxRcntUpd16(i);
break;
case 0x3: //GATE_ON_Start
break;
default:
SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n");
break;
}
}
void psxCheckStartGate(int counter) { //Check Gate events when Vsync Starts
int i = counter;
if(counter == 0){
void psxCheckEndGate32(int i)
{
assert(i >= 3);
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxCounters[i].count += (u32)psxRcntRcount32(i); //Only counts when signal is on
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxCounters[i].mode &= ~0x10000000;
psxRcntUpd32(i);
break;
case 0x3: //GATE_ON_Start
break;
default:
SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n");
break;
}
}
void psxCheckStartGate16(int i)
{
assert( i < 3 );
//Check Gate events when Vsync Starts
if(i == 0)
{
if((psxCounters[1].mode & 0x101) == 0x100 || (psxCounters[1].mode & 0x10000101) == 0x101)psxCounters[1].count++;
if((psxCounters[3].mode & 0x101) == 0x100 || (psxCounters[3].mode & 0x10000101) == 0x101)psxCounters[3].count++;
/*if(SPU2async)
{
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
//SysPrintf("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
psxCounters[6].sCycleT = psxRegs.cycle;
}*/
}
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
if(counter < 3){ //Gates for 16bit counters
//SysPrintf("PSX Gate %x\n", i);
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxRcntUpd32(i);
psxCounters[i].mode |= 0x10000000;
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxRcntReset32(i);
psxCounters[i].mode |= 0x10000000;
break;
case 0x3: //GATE_ON_Start
psxCounters[i].mode &= ~0x10000000;
break;
default:
SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n");
break;
}
//SysPrintf("PSX Gate %x\n", i);
switch((psxCounters[i].mode & 0x6) >> 1)
{
case 0x0: //GATE_ON_count
psxRcntUpd32(i);
psxCounters[i].mode |= 0x10000000;
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd16(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxRcntReset32(i);
psxCounters[i].mode |= 0x10000000;
break;
case 0x3: //GATE_ON_Start
psxCounters[i].mode &= ~0x10000000;
break;
default:
SysPrintf("PCSX2 Warning: 16bit IOP Counter Gate Not Set!\n");
break;
}
}
if(counter >= 3){ //Gates for 32bit counters
//SysPrintf("PSX Gate %x\n", i);
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxRcntUpd32(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxRcntReset32(i);
psxCounters[i].mode |= 0x10000000;
break;
case 0x3: //GATE_ON_Start
psxCounters[i].mode &= ~0x10000000;
break;
default:
SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n");
break;
}
void psxCheckStartGate32(int i)
{
assert(i >= 3);
if((psxCounters[i].mode & 0x1) == 0) return; //Ignore Gate
//SysPrintf("PSX Gate %x\n", i);
switch((psxCounters[i].mode & 0x6) >> 1) {
case 0x0: //GATE_ON_count
psxRcntUpd32(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x1: //GATE_ON_ClearStart
if(psxCounters[i].mode & 0x10000000)psxRcntUpd32(i);
psxCounters[i].mode &= ~0x10000000;
break;
case 0x2: //GATE_ON_Clear_OFF_Start
psxRcntReset32(i);
psxCounters[i].mode |= 0x10000000;
break;
case 0x3: //GATE_ON_Start
psxCounters[i].mode &= ~0x10000000;
break;
default:
SysPrintf("PCSX2 Warning: 32bit IOP Counter Gate Not Set!\n");
break;
}
}

View File

@ -50,7 +50,9 @@ int psxRcntFreeze(gzFile f, int Mode);
void psxVBlankStart();
void psxVBlankEnd();
void psxCheckStartGate(int counter);
void psxCheckEndGate(int counter);
void psxCheckStartGate16(int counter);
void psxCheckEndGate16(int counter);
void psxCheckStartGate32(int counter);
void psxCheckEndGate32(int counter);
#endif /* __PSXCOUNTERS_H__ */

View File

@ -33,6 +33,8 @@
using namespace std;
extern "C" {
#include "zlib.h"
#include "Elfheader.h"
#include "Misc.h"