*Experimental* Sync issues are very sensitive buggers. There could be some breakages in this revision, so keep an eye out, folks.

Improved the responsiveness and efficiency of the EE's INTC handler by having it raise exceptions immediately in response to interrupt handlers (the old method delayed the exception until the next branch test, which meant that a lot of common interrupts like vsync, GS, GIF/VIF, etc resulted in two consecutive branch tests when they should have needed only one).

Moved the gsIrq() in Counters.c from the vsyncStart() to the vsyncEnd().  The gsIrq() supposedly happens on the falling edge of the vsync, so this *should* be more correct.  (but more correct doesn't always mean better)

Added iopIntcTest() functions to the IOP's synchronization tools, so the IOP should now "correctly" raise exceptions when it re-enables pending IRQs.

git-svn-id: http://pcsx2-playground.googlecode.com/svn/trunk@547 a6443dda-0b58-4228-96e9-037be469359c
This commit is contained in:
Jake.Stine 2009-01-04 06:38:22 +00:00 committed by Gregory Hainaut
parent bbfb6ac41a
commit 4524fd919e
19 changed files with 357 additions and 305 deletions

View File

@ -206,7 +206,7 @@ static void CDVD_INT(int eCycle)
static void cdvdSetIrq( uint id = (1<<Irq_CommandComplete) )
{
cdvd.PwOff |= id;
psxHu32(0x1070)|= 0x4;
iopIntcIrq( 2 );
hwIntcIrq(INTC_SBUS);
psxSetNextBranchDelta( 20 );
}

View File

@ -489,7 +489,8 @@ void cdrInterrupt() {
break;
}
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18) psxHu32(0x1070)|=0x4;
if (cdr.Stat != NoIntr && cdr.Reg2 != 0x18)
psxHu32(0x1070)|= 0x4;
CDR_LOG("Cdr Interrupt %x\n", Irq);
}
@ -554,7 +555,7 @@ void cdrReadInterrupt() {
CDREAD_INT((cdr.Mode & 0x80) ? (cdReadTime / 2) : cdReadTime);
}
psxHu32(0x1070)|=0x4;
psxHu32(0x1070)|= 0x4;
return;
}
@ -827,7 +828,8 @@ void cdrWrite1(u8 rt) {
CDR_LOG("Unknown Cmd: %x\n", cdr.Cmd);
return;
}
if (cdr.Stat != NoIntr) psxHu32(0x1070)|=0x4;
if (cdr.Stat != NoIntr)
iopIntcIrq( 2 );
}
u8 cdrRead2(void) {

View File

@ -391,24 +391,38 @@ static __forceinline void frameLimit()
}
}
static __forceinline void VSyncStart(u32 sCycle) // VSync Start
static __forceinline void VSyncStart(u32 sCycle)
{
vSyncDebugStuff(); // EE Profiling and Debug code
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq(); //GS Irq
hwIntcIrq(2); // HW Irq
psxVBlankStart(); // psxCounters vBlank Start
// HACK : For some inexplicable reason, having the IntcIrq(2) handled during the
// current Event Test breaks some games (Grandia 2 at bootup). I can't fathom why.
// To fix I fool the Intc handler into thinking that we're not in an event test, so
// that it schedules the handler into the future by 4 cycles. (air)
eeEventTestIsActive = false;
hwIntcIrq(2);
eeEventTestIsActive = true;
psxVBlankStart();
if (gates) rcntStartGate(0x8, sCycle); // Counters Start Gate code
if (Config.Patch) applypatch(1); // Apply patches (ToDo: clean up patch code)
cpuRegs.eCycle[30] = 8;
}
static __forceinline void VSyncEnd(u32 sCycle) // VSync End
static __forceinline void VSyncEnd(u32 sCycle)
{
iFrame++;
// I moved the gsIrq trigger to the falling edge, where I've been told it is
// more correct. (air)
if ((CSRw & 0x8)) GSCSRr|= 0x8;
if (!(GSIMR&0x800)) gsIrq();
if( g_vu1SkipCount > 0 )
{
gsPostVsyncEnd( false );

View File

@ -932,8 +932,7 @@ void hwWrite32(u32 mem, u32 value) {
psHu16(0xe010)&= ~(value & 0xffff); // clear on 1
psHu16(0xe012) ^= (u16)(value >> 16);
if ((cpuRegs.CP0.n.Status.val & 0x10807) == 0x10801)
cpuTestDMACInts();
cpuTestDMACInts();
break;
//------------------------------------------------------------------
case 0x1000f000: // INTC_STAT
@ -945,7 +944,6 @@ void hwWrite32(u32 mem, u32 value) {
case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x\n", value);
psHu32(0xf010) ^= (u16)value;
cpuTestINTCInts();
break;
//------------------------------------------------------------------
@ -984,22 +982,18 @@ void hwWrite32(u32 mem, u32 value) {
//------------------------------------------------------------------
case 0x1000f130:
case 0x1000f410:
#ifdef PCSX2_DEVBUILD
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status);
#endif
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val);
break;
//------------------------------------------------------------------
default:
#ifndef PCSX2_VIRTUAL_MEM
if (mem < 0x10010000)
if (mem < 0x10010000)
#endif
{
psHu32(mem) = value;
}
#ifdef PCSX2_DEVBUILD
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status);
#endif
break;
{
psHu32(mem) = value;
}
HW_LOG("Unknown Hardware write 32 at %x with value %x (%x)\n", mem, value, cpuRegs.CP0.n.Status.val);
break;
}
}
@ -1021,9 +1015,7 @@ void hwWrite64(u32 mem, u64 value) {
switch (mem) {
case GIF_CTRL:
#ifdef PCSX2_DEVBUILD
SysPrintf("GIF_CTRL write 64\n", value);
#endif
DevCon::Status("GIF_CTRL write 64", value);
psHu32(mem) = value & 0x8;
if(value & 0x1) {
gsGIFReset();
@ -1038,7 +1030,7 @@ void hwWrite64(u32 mem, u64 value) {
case GIF_MODE:
#ifdef GSPATH3FIX
SysPrintf("GIFMODE64 %x\n", value);
Console::Status("GIFMODE64 %x\n", value);
#endif
psHu64(GIF_MODE) = value;
if (value & 0x1) psHu32(GIF_STAT)|= 0x1;
@ -1055,12 +1047,10 @@ void hwWrite64(u32 mem, u64 value) {
DmaExec(dmaGIF, mem, value);
break;
#ifdef HW_LOG
case 0x1000e000: // DMAC_CTRL
HW_LOG("DMAC_CTRL Write 64bit %x\n", value);
psHu64(mem) = value;
break;
#endif
case 0x1000e010: // DMAC_STAT
HW_LOG("DMAC_STAT Write 64bit %x\n", value);
@ -1073,8 +1063,7 @@ void hwWrite64(u32 mem, u64 value) {
else psHu16(0xe012)|= 1<<i;
}
}
if ((cpuRegs.CP0.n.Status.val & 0x10807) == 0x10801)
cpuTestDMACInts();
cpuTestDMACInts();
break;
case 0x1000f590: // DMAC_ENABLEW
@ -1084,17 +1073,17 @@ void hwWrite64(u32 mem, u64 value) {
case 0x1000f000: // INTC_STAT
HW_LOG("INTC_STAT Write 64bit %x\n", value);
psHu32(0xf000)&=~value;
psHu32(INTC_STAT)&=~value;
cpuTestINTCInts();
break;
case 0x1000f010: // INTC_MASK
HW_LOG("INTC_MASK Write 32bit %x\n", value);
for (i=0; i<16; i++) { // reverse on 1
int s = (1<<i);
const int s = (1<<i);
if (value & s) {
if (psHu32(0xf010) & (1<<i)) psHu32(0xf010)&= ~(1<<i);
else psHu32(0xf010)|= 1<<i;
if (psHu32(INTC_MASK) & s) psHu32(INTC_MASK)&= ~s;
else psHu32(INTC_MASK)|= s;
}
}
cpuTestINTCInts();
@ -1104,12 +1093,11 @@ void hwWrite64(u32 mem, u64 value) {
case 0x1000f410:
case 0x1000f430:
break;
default:
psHu64(mem) = value;
#ifdef PCSX2_DEVBUILD
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status);
#endif
HW_LOG("Unknown Hardware write 64 at %x with value %x (status=%x)\n",mem,value, cpuRegs.CP0.n.Status.val);
break;
}
}
@ -1134,9 +1122,7 @@ void hwWrite128(u32 mem, const u64 *value) {
psHu64(mem ) = value[0];
psHu64(mem+8) = value[1];
#ifdef PCSX2_DEVBUILD
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status);
#endif
HW_LOG("Unknown Hardware write 128 at %x with value %x_%x (status=%x)\n", mem, value[1], value[0], cpuRegs.CP0.n.Status.val);
break;
}
}
@ -1146,7 +1132,7 @@ __forceinline void intcInterrupt() {
if ((cpuRegs.CP0.n.Status.val & 0x400) != 0x400) return;
if ((psHu32(INTC_STAT)) == 0) {
SysPrintf("*PCSX2*: intcInterrupt already cleared\n");
DevCon::Notice("*PCSX2*: intcInterrupt already cleared");
return;
}
if ((psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0) return;
@ -1160,24 +1146,13 @@ __forceinline void intcInterrupt() {
cpuException(0x400, cpuRegs.branch);
}
// fixme: dead/unused code?
/*void dmacTestInterrupt() {
cpuRegs.interrupt &= ~(1 << 31);
if ((cpuRegs.CP0.n.Status.val & 0x800) != 0x800) return;
if ((psHu16(0xe012) & psHu16(0xe010) ||
psHu16(0xe010) & 0x8000) == 0) return;
if((psHu32(DMAC_CTRL) & 0x1) == 0) return;
}*/
__forceinline void dmacInterrupt()
{
cpuRegs.interrupt &= ~(1 << 31);
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
if ((psHu16(0xe012) & psHu16(0xe010) ||
psHu16(0xe010) & 0x8000) == 0) return;
if( ((psHu16(0xe012) & psHu16(0xe010)) == 0 ) &&
( psHu16(0xe010) & 0x8000) == 0 ) return;
if((psHu32(DMAC_CTRL) & 0x1) == 0) return;
@ -1188,10 +1163,8 @@ __forceinline void dmacInterrupt()
}
void hwIntcIrq(int n) {
//if( psHu32(INTC_MASK) & (1<<n) ) {
psHu32(INTC_STAT)|= 1<<n;
cpuTestINTCInts();
//}
psHu32(INTC_STAT)|= 1<<n;
cpuTestINTCInts();
}
void hwDmacIrq(int n) {

View File

@ -722,21 +722,23 @@ void _eeWriteConstMem16(u32 mem, int mmreg)
else MOV16RtoM(mem, mmreg);
}
// op - 0 for AND, 1 for OR
void _eeWriteConstMem16OP(u32 mem, int mmreg, int op)
{
assert( !IS_XMMREG(mmreg) && !IS_MMXREG(mmreg) );
switch(op) {
case 0: // and
case 0: // AND operation
if( IS_EECONSTREG(mmreg) ) AND16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) AND16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else AND16RtoM(mem, mmreg);
break;
case 1: // and
case 1: // OR operation
if( IS_EECONSTREG(mmreg) ) OR16ItoM(mem, g_cpuConstRegs[((mmreg>>16)&0x1f)].UL[0]);
else if( IS_PSXCONSTREG(mmreg) ) OR16ItoM(mem, g_psxConstRegs[((mmreg>>16)&0x1f)]);
else OR16RtoM(mem, mmreg);
break;
default: assert(0);
jNO_DEFAULT
}
}
@ -2595,7 +2597,12 @@ static u8* m_psAllMem = NULL;
int memInit()
{
#ifdef __LINUX__
InstallLinuxExceptionHandler();
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &SysPageFaultExceptionFilter;
sigaction(SIGSEGV, &sa, NULL);
#endif
if (!vtlb_Init()) return -1;
@ -2923,29 +2930,14 @@ int SysPageFaultExceptionFilter(EXCEPTION_POINTERS* eps)
}
#else
#include "errno.h"
__forceinline void __fastcall InstallLinuxExceptionHandler()
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &SysPageFaultExceptionFilter;
sigaction(SIGSEGV, &sa, NULL);
}
// Linux implementation of SIGSEGV handler. Bind it using sigaction().
// This is my shot in the dark. Probably needs some work. Good luck! (air)
__forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t *info, void * )
{
int err;
u32 pagesize = getpagesize();
//DevCon::Error("SysPageFaultExceptionFilter!");
//Console::Error("SysPageFaultExceptionFilter!");
// get bad virtual address
u32 offset = (u8*)info->si_addr - psM;
uptr pageoffset = ( offset / pagesize ) * pagesize;
if (offset>=Ps2MemSize::Base)
{
@ -2954,9 +2946,8 @@ __forceinline void __fastcall SysPageFaultExceptionFilter( int signal, siginfo_t
assert( false );
}
err = mprotect( &psM[pageoffset], pagesize, PROT_READ | PROT_WRITE );
if (err) DevCon::Error("SysPageFaultExceptionFilter: %s", strerror(errno));
mprotect(&psM[offset], 1, PROT_READ|PROT_WRITE);
offset>>=12;
psMPWC[(offset/32)]|=(1<<(offset&31));

View File

@ -16,6 +16,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// Note on INTC usage: All counters code is always called from inside the context of an
// event test, so instead of using the iopTestIntc we just set the 0x1070 flags directly.
// The EventText function will pick it up.
#include "PrecompiledHeader.h"
#include <math.h>

View File

@ -26,60 +26,72 @@
// Dma11/12 in PsxSio2.c
int iopsifbusy[2] = { 0, 0 };
void psxDma4(u32 madr, u32 bcr, u32 chcr) { // SPU
const int size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer
/*if (chcr & 0x400) SysPrintf("SPU 2 DMA 4 linked list chain mode! chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr);
if (chcr & 0x40000000) SysPrintf("SPU 2 DMA 4 Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr);
if ((chcr & 0x1) == 0) SysPrintf("SPU 2 DMA 4 loading from spu2 memory chcr = %x madr = %x bcr = %x\n", chcr, madr, bcr);*/
static void __fastcall psxDmaGeneric(u32 madr, u32 bcr, u32 chcr, u32 spuCore, _SPU2writeDMA4Mem spu2WriteFunc )
{
const char dmaNum = spuCore ? '7' : '4';
/*if (chcr & 0x400) DevCon::Status("SPU 2 DMA %c linked list chain mode! chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);
if (chcr & 0x40000000) DevCon::Notice("SPU 2 DMA %c Unusual bit set on 'to' direction chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);
if ((chcr & 0x1) == 0) DevCon::Status("SPU 2 DMA %c loading from spu2 memory chcr = %x madr = %x bcr = %x\n", dmaNum, chcr, madr, bcr);*/
const int size = (bcr >> 16) * (bcr & 0xFFFF);
// Update the spu2 to the current cycle before initiating the DMA
if(SPU2async)
{
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
{
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
//Console::Status("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
//SysPrintf("cycles sent to SPU2 %x\n", psxRegs.cycle - psxCounters[6].sCycleT);
psxCounters[6].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = size * 3;
psxNextCounter -= (psxRegs.cycle-psxNextsCounter);
psxNextsCounter = psxRegs.cycle;
if(psxCounters[6].CycleT < psxNextCounter) psxNextCounter = psxCounters[6].CycleT;
if(psxCounters[6].CycleT < psxNextCounter)
psxNextCounter = psxCounters[6].CycleT;
}
switch (chcr) {
case 0x01000201: //cpu to spu transfer
PSXDMA_LOG("*** DMA 4 - SPU mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
//SysPrintf("DMA4 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF));
SPU2writeDMA4Mem((u16 *)PSXM(madr), size*2);
break;
case 0x01000200: //spu to cpu transfer
PSXDMA_LOG("*** DMA 4 - SPU spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
//SysPrintf("DMA4 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF));
SPU2readDMA4Mem((u16 *)PSXM(madr), size*2);
psxCpu->Clear(HW_DMA4_MADR, size);
break;
switch (chcr)
{
case 0x01000201: //cpu to spu2 transfer
PSXDMA_LOG("*** DMA %c - mem2spu *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr);
spu2WriteFunc((u16 *)PSXM(madr), size*2);
break;
case 0x01000200: //spu2 to cpu transfer
PSXDMA_LOG("*** DMA %c - spu2mem *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr);
spu2WriteFunc((u16 *)PSXM(madr), size*2);
psxCpu->Clear(spuCore ? HW_DMA7_MADR : HW_DMA4_MADR, size);
break;
default:
SysPrintf("*** DMA 4 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
break;
Console::Error("*** DMA %c - SPU unknown *** %lx addr = %lx size = %lx\n", dmaNum, chcr, madr, bcr);
break;
}
}
int psxDma4Interrupt() {
HW_DMA4_CHCR &= ~0x01000000;
psxDmaInterrupt(4);
psxHu32(0x1070)|= 1<<9;
return 1;
void psxDma4(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 0
{
psxDmaGeneric( madr, bcr, chcr, 0, SPU2writeDMA4Mem );
}
void psxDma2(u32 madr, u32 bcr, u32 chcr) { // GPU
int psxDma4Interrupt()
{
HW_DMA4_CHCR &= ~0x01000000;
psxDmaInterrupt(4);
iopIntcIrq( 9 );
return 1;
}
void psxDma2(u32 madr, u32 bcr, u32 chcr) // GPU
{
HW_DMA2_CHCR &= ~0x01000000;
psxDmaInterrupt(2);
}
void psxDma6(u32 madr, u32 bcr, u32 chcr) {
void psxDma6(u32 madr, u32 bcr, u32 chcr)
{
u32 *mem = (u32 *)PSXM(madr);
PSXDMA_LOG("*** DMA 6 - OT *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
@ -98,50 +110,22 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr) {
psxDmaInterrupt(6);
}
void psxDma7(u32 madr, u32 bcr, u32 chcr) {
int size = (bcr >> 16) * (bcr & 0xFFFF);
if(SPU2async)
{
SPU2async(psxRegs.cycle - psxCounters[6].sCycleT);
psxCounters[6].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = size * 3;
psxNextCounter -= (psxRegs.cycle-psxNextsCounter);
psxNextsCounter = psxRegs.cycle;
if(psxCounters[6].CycleT < psxNextCounter) psxNextCounter = psxCounters[6].CycleT;
}
switch (chcr) {
case 0x01000201: //cpu to spu2 transfer
PSXDMA_LOG("*** DMA 7 - SPU2 mem2spu *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
//SysPrintf("DMA7 write blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF));
SPU2writeDMA7Mem((u16 *)PSXM(madr), size*2);
break;
case 0x01000200: //spu2 to cpu transfer
PSXDMA_LOG("*** DMA 7 - SPU2 spu2mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
//SysPrintf("DMA7 read blocks %x, size per block %x\n", (bcr >> 16), (bcr & 0xFFFF));
SPU2readDMA7Mem((u16 *)PSXM(madr), size*2);
psxCpu->Clear(HW_DMA7_MADR, size);
break;
default:
SysPrintf("*** DMA 7 - SPU unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
break;
}
void psxDma7(u32 madr, u32 bcr, u32 chcr) // SPU2's Core 1
{
psxDmaGeneric( madr, bcr, chcr, 1, SPU2writeDMA7Mem );
}
int psxDma7Interrupt() {
HW_DMA7_CHCR &= ~0x01000000;
psxDmaInterrupt2(0);
return 1;
int psxDma7Interrupt()
{
HW_DMA7_CHCR &= ~0x01000000;
psxDmaInterrupt2(0);
//iopIntcIrq( 9 );
return 1;
}
extern int eesifbusy[2];
void psxDma9(u32 madr, u32 bcr, u32 chcr) {
void psxDma9(u32 madr, u32 bcr, u32 chcr)
{
SIF_LOG("IOP: dmaSIF0 chcr = %lx, madr = %lx, bcr = %lx, tadr = %lx\n", chcr, madr, bcr, HW_DMA9_TADR);
iopsifbusy[0] = 1;
@ -171,25 +155,23 @@ void psxDma10(u32 madr, u32 bcr, u32 chcr) {
}
void psxDma8(u32 madr, u32 bcr, u32 chcr) {
int size;
const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8;
switch (chcr & 0x01000201) {
case 0x01000201: //cpu to dev9 transfer
PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
DEV9writeDMA8Mem((u32*)PSXM(madr), size);
break;
size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer
DEV9writeDMA8Mem((u32*)PSXM(madr), size*8);
break;
case 0x01000200: //dev9 to cpu transfer
PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
DEV9readDMA8Mem((u32*)PSXM(madr), size);
break;
size = (bcr >> 16) * (bcr & 0xFFFF); // Number of blocks to transfer
DEV9readDMA8Mem((u32*)PSXM(madr), size*8);
break;
default:
PSXDMA_LOG("*** DMA 8 - DEV9 unknown *** %lx addr = %lx size = %lx\n", chcr, madr, bcr);
break;
break;
}
HW_DMA8_CHCR &= ~0x01000000;
psxDmaInterrupt2(1);
@ -198,8 +180,8 @@ void psxDma8(u32 madr, u32 bcr, u32 chcr) {
void dev9Interrupt() {
if( (dev9Handler != NULL) && (dev9Handler() != 1) )
return;
psxHu32(0x1070)|= 1<<13;
iopIntcIrq( 13 );
hwIntcIrq(INTC_SBUS);
}
@ -211,7 +193,7 @@ void usbInterrupt() {
if( usbHandler != NULL && (usbHandler() != 1) )
return;
psxHu32(0x1070)|= 1<<22;
iopIntcIrq( 22 );
hwIntcIrq(INTC_SBUS);
}
@ -220,7 +202,7 @@ void usbIrq(int cycles) {
}
void fwIrq() {
psxHu32(0x1070)|= 1<<24;
iopIntcIrq( 24 );
hwIntcIrq(INTC_SBUS);
}
@ -239,6 +221,12 @@ void spu2DMA7Irq() {
}
void spu2Irq() {
psxHu32(0x1070)|= 1<<9;
iopIntcIrq( 9 );
hwIntcIrq(INTC_SBUS);
}
void iopIntcIrq( uint irqType )
{
psxHu32(0x1070)|= 1<<irqType;
iopTestIntc();
}

View File

@ -37,6 +37,10 @@ void usbIrq(int cycles);
void fwIrq();
void spu2Irq();
extern void iopIntcIrq( uint irqType );
extern void iopTestIntc();
extern DEV9handler dev9Handler;
extern USBhandler usbHandler;

View File

@ -704,9 +704,9 @@ void psxHwWrite16(u32 add, u16 value) {
if (add >= 0x1f801600 && add < 0x1f801700) {
USBwrite16(add, value); return;
}
#ifdef PCSX2_DEVBUILD
if((add & 0xf) == 0x9) SysPrintf("16bit write (possible chcr set) %x value %x\n", add, value);
#endif
if((add & 0xf) == 0x9) DevCon::WriteLn("16bit write (possible chcr set) %x value %x", add, value);
switch (add) {
case 0x1f801040:
sioWrite8((u8)value);
@ -741,13 +741,23 @@ void psxHwWrite16(u32 add, u16 value) {
// if (Config.SpuIrq) psxHu16(0x1070) |= 0x200;
psxHu16(0x1070) &= value;
return;
case 0x1f801074: PSXHW_LOG("IMASK 16bit write %x\n", value);
case 0x1f801074:
PSXHW_LOG("IMASK 16bit write %x\n", value);
psxHu16(0x1074) = value;
iopTestIntc();
return;
case 0x1f801078: // see the 32-bit version for notes!
PSXHW_LOG("ICTRL 16bit write %x\n", value);
psxHu16(0x1078) = value;
iopTestIntc();
return;
case 0x1f8010c4:
PSXHW_LOG("DMA4 BCR_size 16bit write %lx\n", value);
psxHu16(0x10c4) = value; return; // DMA4 bcr_size
psxHu16(0x10c4) = value;
return; // DMA4 bcr_size
case 0x1f8010c6:
PSXHW_LOG("DMA4 BCR_count 16bit write %lx\n", value);
@ -868,6 +878,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxHu32(add) = value;
return; // Ram size
//------------------------------------------------------------------
case 0x1f801070:
PSXHW_LOG("IREG 32bit write %lx\n", value);
// if (Config.Sio) psxHu32(0x1070) |= 0x80;
@ -878,13 +889,16 @@ void psxHwWrite32(u32 add, u32 value) {
case 0x1f801074:
PSXHW_LOG("IMASK 32bit write %lx\n", value);
psxHu32(0x1074) = value;
iopTestIntc();
return;
case 0x1f801078:
PSXHW_LOG("ICTRL 32bit write %lx\n", value);
psxHu32(0x1078) = value;//1; //According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p
psxHu32(0x1078) = value; //1; //According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p
iopTestIntc();
return;
//------------------------------------------------------------------
//SSBus registers
case 0x1f801000:
psxHu32(0x1000) = value;
@ -958,6 +972,8 @@ void psxHwWrite32(u32 add, u32 value) {
psxHu32(0x1420) = value;
PSXHW_LOG("SSBUS <dev9_delay1> 32bit write %lx\n", value);
return;
//------------------------------------------------------------------
case 0x1f801080:
PSXHW_LOG("DMA0 MADR 32bit write %lx\n", value);
HW_DMA0_MADR = value; return; // DMA0 madr
@ -970,6 +986,7 @@ void psxHwWrite32(u32 add, u32 value) {
// DmaExec(0);
return;
//------------------------------------------------------------------
case 0x1f801090:
PSXHW_LOG("DMA1 MADR 32bit write %lx\n", value);
HW_DMA1_MADR = value; return; // DMA1 madr
@ -982,6 +999,7 @@ void psxHwWrite32(u32 add, u32 value) {
// DmaExec(1);
return;
//------------------------------------------------------------------
case 0x1f8010a0:
PSXHW_LOG("DMA2 MADR 32bit write %lx\n", value);
HW_DMA2_MADR = value; return; // DMA2 madr
@ -994,6 +1012,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec(2);
return;
//------------------------------------------------------------------
case 0x1f8010b0:
PSXHW_LOG("DMA3 MADR 32bit write %lx\n", value);
HW_DMA3_MADR = value; return; // DMA3 madr
@ -1007,6 +1026,7 @@ void psxHwWrite32(u32 add, u32 value) {
return;
//------------------------------------------------------------------
case 0x1f8010c0:
PSXHW_LOG("DMA4 MADR 32bit write %lx\n", value);
SPU2WriteMemAddr(0,value);
@ -1020,6 +1040,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec(4);
return;
//------------------------------------------------------------------
#if 0
case 0x1f8010d0: break; //DMA5write_madr();
case 0x1f8010d4: break; //DMA5write_bcr();
@ -1038,6 +1059,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec(6);
return;
//------------------------------------------------------------------
case 0x1f801500:
PSXHW_LOG("DMA7 MADR 32bit write %lx\n", value);
SPU2WriteMemAddr(1,value);
@ -1051,6 +1073,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(7);
return;
//------------------------------------------------------------------
case 0x1f801510:
PSXHW_LOG("DMA8 MADR 32bit write %lx\n", value);
HW_DMA8_MADR = value; return; // DMA8 madr
@ -1063,6 +1086,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(8);
return;
//------------------------------------------------------------------
case 0x1f801520:
PSXHW_LOG("DMA9 MADR 32bit write %lx\n", value);
HW_DMA9_MADR = value; return; // DMA9 madr
@ -1078,6 +1102,7 @@ void psxHwWrite32(u32 add, u32 value) {
PSXHW_LOG("DMA9 TADR 32bit write %lx\n", value);
HW_DMA9_TADR = value; return; // DMA9 tadr
//------------------------------------------------------------------
case 0x1f801530:
PSXHW_LOG("DMA10 MADR 32bit write %lx\n", value);
HW_DMA10_MADR = value; return; // DMA10 madr
@ -1090,6 +1115,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(10);
return;
//------------------------------------------------------------------
case 0x1f801540:
PSXHW_LOG("DMA11 SIO2in MADR 32bit write %lx\n", value);
HW_DMA11_MADR = value; return;
@ -1103,6 +1129,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(11);
return;
//------------------------------------------------------------------
case 0x1f801550:
PSXHW_LOG("DMA12 SIO2out MADR 32bit write %lx\n", value);
HW_DMA12_MADR = value; return;
@ -1116,6 +1143,7 @@ void psxHwWrite32(u32 add, u32 value) {
DmaExec2(12);
return;
//------------------------------------------------------------------
case 0x1f801570:
psxHu32(0x1570) = value;
PSXHW_LOG("DMA PCR2 32bit write %lx\n", value);
@ -1130,17 +1158,18 @@ void psxHwWrite32(u32 add, u32 value) {
{
u32 tmp = (~value) & HW_DMA_ICR;
HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp;
return;
}
return;
case 0x1f801574:
PSXHW_LOG("DMA ICR2 32bit write %lx\n", value);
{
u32 tmp = (~value) & HW_DMA_ICR2;
HW_DMA_ICR2 = ((tmp ^ value) & 0xffffff) ^ tmp;
return;
}
return;
//------------------------------------------------------------------
/* case 0x1f801810:
PSXHW_LOG("GPU DATA 32bit write %lx\n", value);
GPU_writeData(value); return;
@ -1213,9 +1242,10 @@ void psxHwWrite32(u32 add, u32 value) {
PSXCNT_LOG("COUNTER 5 TARGET 32bit write %lx\n", value);
psxRcntWtarget32(5, value); return;
//------------------------------------------------------------------
case 0x1f8014c0:
PSXHW_LOG("RTC_HOLDMODE 32bit write %lx\n", value);
SysPrintf("RTC_HOLDMODE 32bit write %lx\n", value);
Console::Notice("** RTC_HOLDMODE 32bit write %lx", value);
break;
case 0x1f801450:
@ -1230,6 +1260,7 @@ void psxHwWrite32(u32 add, u32 value) {
psxHu32(0x1450) = /*(*/value/* & (~0x8)) | (psxHu32(0x1450) & 0x8)*/;
return;
//------------------------------------------------------------------
case 0x1F808200:
case 0x1F808204:
case 0x1F808208:
@ -1279,6 +1310,7 @@ void psxHwWrite32(u32 add, u32 value) {
PSXHW_LOG("SIO2 write INTR <- %lx\n", value);
sio2_setIntr(value); return;
//------------------------------------------------------------------
default:
psxHu32(add) = value;
PSXHW_LOG("*Unknown 32bit write at address %lx value %lx\n", add, value);
@ -1350,20 +1382,13 @@ void psxHw4Write8(u32 add, u8 value) {
case 0x1f40200A: cdvdWrite0A(value); return;
case 0x1f40200F: cdvdWrite0F(value); return;
case 0x1f402014: cdvdWrite14(value); return;
case 0x1f402016:
cdvdWrite16(value);
//fixme - are these supposed to be here?
FreezeMMXRegs(0);
FreezeXMMRegs(0);
return;
case 0x1f402016: cdvdWrite16(value); return;
case 0x1f402017: cdvdWrite17(value); return;
case 0x1f402018: cdvdWrite18(value); return;
case 0x1f40203A: cdvdWrite3A(value); return;
default:
// note: use SysPrintF to notify console since this is a potentially serious
// emulation problem:
//PSXHW_LOG("*Unknown 8bit write at address %lx value %x\n", add, value);
SysPrintf("*Unknown 8bit write at address %lx value %x\n", add, value);
Console::Notice("*Unknown 8bit write at address %lx value %x", add, value);
return;
}
PSXHW_LOG("*Known 8bit write at address %lx value %x\n", add, value);
@ -1373,7 +1398,7 @@ void psxDmaInterrupt(int n) {
if (HW_DMA_ICR & (1 << (16 + n))) {
HW_DMA_ICR|= (1 << (24 + n));
psxRegs.CP0.n.Cause |= 1 << (9 + n);
psxHu32(0x1070) |= 8;
iopIntcIrq( 3 );
}
}
@ -1387,6 +1412,6 @@ void psxDmaInterrupt2(int n) {
}*/
HW_DMA_ICR2|= (1 << (24 + n));
psxRegs.CP0.n.Cause |= 1 << (16 + n);
psxHu32(0x1070) |= 8;
iopIntcIrq( 3 );
}
}

View File

@ -117,8 +117,7 @@ void sio2_setCtrl(u32 value){
if (sio2.ctrl & 1){ //recv packet
//handle data that had been sent
//trigger interupt for SIO2
psxHu32(0x1070)|=0x20000;
iopIntcIrq( 17 );
//SBUS
sio2.recvIndex=0;
sio2.ctrl &= ~1;

View File

@ -43,8 +43,9 @@ s32 psxCycleEE = -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.
int iopBranchAction = 0;
bool iopBranchAction = false;
bool iopEventTestIsActive = false;
PCSX2_ALIGNED16(psxRegisters psxRegs);
@ -245,25 +246,38 @@ void psxBranchTest()
if( psxTestCycle( psxNextsCounter, psxNextCounter ) )
{
psxRcntUpdate();
iopBranchAction = 1;
iopBranchAction = true;
}
// start the next branch at the next counter event by default
// the interrupt code below will assign nearer branches if needed.
g_psxNextBranchCycle = psxNextsCounter+psxNextCounter;
if (psxRegs.interrupt) _psxTestInterrupts();
if (psxHu32(0x1078)) {
if(psxHu32(0x1070) & psxHu32(0x1074)){
if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401)
{
// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074));
psxException(0, 0);
iopBranchAction = 1;
}
}
if (psxRegs.interrupt)
{
iopEventTestIsActive = true;
_psxTestInterrupts();
iopEventTestIsActive = false;
}
if( psxHu32(0x1078) == 0 ) return;
if( (psxHu32(0x1070) & psxHu32(0x1074)) == 0 ) return;
if ((psxRegs.CP0.n.Status & 0xFE01) >= 0x401)
{
// PSXCPU_LOG("Interrupt: %x %x\n", HWMu32(0x1070), HWMu32(0x1074));
psxException(0, 0);
iopBranchAction = true;
}
}
void iopTestIntc()
{
if( iopEventTestIsActive ) return;
if( psxHu32(0x1078) == 0 ) return;
if( (psxHu32(0x1070) & psxHu32(0x1074)) == 0 ) return;
psxSetNextBranchDelta( 4 );
}
void psxExecuteBios() {

View File

@ -214,6 +214,7 @@ void psxExecuteBios();
extern s32 psxNextCounter;
extern u32 psxNextsCounter;
extern int iopBranchAction;
extern bool iopBranchAction;
extern bool iopEventTestIsActive;
#endif /* __R3000A_H__ */

View File

@ -45,6 +45,8 @@ u32 bExecBIOS = 0; // set if the BIOS has already been executed
static bool cpuIsInitialized = false;
static uint eeWaitCycles = 1024;
bool eeEventTestIsActive = false;
#ifdef _DEBUG
extern u32 s_vucount;
#endif
@ -208,7 +210,7 @@ void cpuException(u32 code, u32 bd) {
}
} else {
offset = 0x180; //Overrride the cause
SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code);
Console::Notice("cpuException: Status.EXL = 1 cause %x", code);
}
if (cpuRegs.CP0.n.Status.b.BEV == 0) {
cpuRegs.pc = 0x80000000 + offset;
@ -216,7 +218,7 @@ void cpuException(u32 code, u32 bd) {
cpuRegs.pc = 0xBFC00200 + offset;
}
} else { //Error Level 2
Console::Error("FIX ME: Level 2 cpuException");
Console::Error("*PCSX2* FIX ME: Level 2 cpuException");
if((code & 0x38000) <= 0x8000 ) { //Reset / NMI
cpuRegs.pc = 0xBFC00000;
Console::Notice("Reset request");
@ -430,10 +432,6 @@ static __forceinline void _cpuTestInterrupts()
TESTINT(10, vifMFIFOInterrupt);
TESTINT(11, gifMFIFOInterrupt);
}
if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return;
TESTINT(30, intcInterrupt);
TESTINT(31, dmacInterrupt);
}
u32 s_iLastCOP0Cycle = 0;
@ -450,8 +448,9 @@ static __forceinline void _cpuTestTIMR()
// the Count or Compare registers are modified.
if ( (cpuRegs.CP0.n.Status.val & 0x8000) &&
cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) {
SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare);
cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 )
{
Console::Status("timr intr: %x, %x", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare);
cpuException(0x808000, cpuRegs.branch);
}
}
@ -473,11 +472,6 @@ static __forceinline void _cpuTestPERF()
}
}
// Maximum wait between branches. Lower values provide a tighter synchronization between
// the EE and the IOP, but incur more execution overhead.
//#define EE_WAIT_CYCLE 3072 // 2048 is probably stable now, but starting low first
// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
u32 g_nextBranchCycle = 0;
@ -485,6 +479,7 @@ u32 g_nextBranchCycle = 0;
// and the recompiler. (moved here to help alleviate redundant code)
static __forceinline void _cpuBranchTest_Shared()
{
eeEventTestIsActive = true;
g_nextBranchCycle = cpuRegs.cycle + eeWaitCycles;
EEsCycle += cpuRegs.cycle - EEoCycle;
@ -504,10 +499,6 @@ static __forceinline void _cpuBranchTest_Shared()
_cpuTestTIMR();
//#ifdef CPU_LOG
// cpuTestMissingHwInts();
//#endif
// ---- Interrupts -------------
if( cpuRegs.interrupt )
@ -537,41 +528,6 @@ static __forceinline void _cpuBranchTest_Shared()
psxCpu->ExecuteBlock();
}
// The IOP cound be running ahead/behind of us, so adjust the iop's next branch by its
// relative position to the EE (via EEsCycle)
cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );
// Apply the hsync counter's nextCycle
cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT );
// Apply vsync and other counter nextCycles
cpuSetNextBranch( nextsCounter, nextCounter );
}
#ifdef PCSX2_DEVBUILD
extern u8 g_globalXMMSaved;
extern u8 g_globalMMXSaved;
#endif
void cpuBranchTest()
{
// cpuBranchTest should be called from the recompiler only.
assert( Cpu == &recCpu );
#ifdef PCSX2_DEVBUILD
// dont' remove this check unless doing an official release
if( g_globalXMMSaved || g_globalMMXSaved)
SysPrintf("frozen regs have not been restored!!!\n");
assert( !g_globalXMMSaved && !g_globalMMXSaved);
#endif
// Don't need to freeze any regs during a BranchTest.
// Everything has been flushed already.
g_EEFreezeRegs = false;
// Perform counters, ints, and IOP updates:
_cpuBranchTest_Shared();
// ---- VU0 -------------
if (VU0.VI[REG_VPU_STAT].UL & 0x1)
@ -590,6 +546,56 @@ void cpuBranchTest()
// one shot always. That is, when a program is executed the VU1 doesn't even
// bother to return until the program is completely finished.
// ---- Schedule Next Event Test --------------
// The IOP cound be running ahead/behind of us, so adjust the iop's next branch by its
// relative position to the EE (via EEsCycle)
cpuSetNextBranchDelta( ((g_psxNextBranchCycle-psxRegs.cycle)*8) - EEsCycle );
// Apply the hsync counter's nextCycle
cpuSetNextBranch( counters[4].sCycle, counters[4].CycleT );
// Apply vsync and other counter nextCycles
cpuSetNextBranch( nextsCounter, nextCounter );
eeEventTestIsActive = false;
// ---- INTC / DMAC Exceptions -----------------
// Raise the INTC and DMAC interrupts here, which usually throw exceptions.
// This should be done last since the IOP and the VU0 can raise several EE
// exceptions.
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001)
{
TESTINT(30, intcInterrupt);
TESTINT(31, dmacInterrupt);
}
}
#ifdef PCSX2_DEVBUILD
extern u8 g_globalXMMSaved;
extern u8 g_globalMMXSaved;
#endif
void cpuBranchTest()
{
// cpuBranchTest should be called from the recompiler only.
assert( Cpu == &recCpu );
#ifdef PCSX2_DEVBUILD
// dont' remove this check unless doing an official release
if( g_globalXMMSaved || g_globalMMXSaved)
DevCon::Error("Pcsx2 Foopah! Frozen regs have not been restored!!!");
assert( !g_globalXMMSaved && !g_globalMMXSaved);
#endif
// Don't need to freeze any regs during a BranchTest.
// Everything has been flushed already.
g_EEFreezeRegs = false;
// Perform counters, ints, and IOP updates:
_cpuBranchTest_Shared();
#ifdef PCSX2_DEVBUILD
assert( !g_globalXMMSaved && !g_globalMMXSaved);
#endif
@ -616,28 +622,37 @@ __forceinline void CPU_INT( u32 n, s32 ecycle)
cpuSetNextBranchDelta( cpuRegs.eCycle[n] );
}
__forceinline void cpuTestINTCInts() {
void cpuTestINTCInts()
{
if( cpuRegs.interrupt & (1 << 30) ) return;
if( (cpuRegs.CP0.n.Status.val & 0x10407) != 0x10401 ) return;
if( (psHu32(INTC_STAT) & psHu32(INTC_MASK)) == 0 ) return;
if( cpuRegs.interrupt & (1 << 30) ) return;
// fixme: The counters code throws INT30's alot, and most of the time they're
// "late" already, so firing them immediately instead of after the next branch
// (in which case they'll be really late) would be a lot better in theory.
// However, setting this to zero for everything breaks games, so if it's done
// it needs to be done for counters only.
cpuRegs.interrupt|= 1 << 30;
cpuRegs.sCycle[30] = cpuRegs.cycle;
cpuRegs.eCycle[30] = 0;
CPU_INT(30,4);
// only set the next branch delta if the exception won't be handled for
// the current branch...
if( !eeEventTestIsActive )
cpuSetNextBranchDelta( 4 );
}
__forceinline void cpuTestDMACInts() {
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
if ( cpuRegs.interrupt & (1 << 31) ) return;
if ((cpuRegs.CP0.n.Status.val & 0x10807) != 0x10801) return;
if ( ( (psHu16(0xe012) & psHu16(0xe010)) == 0) &&
( (psHu16(0xe010) & 0x8000) == 0) ) return;
CPU_INT(31, 4);
cpuRegs.interrupt|= 1 << 31;
cpuRegs.sCycle[31] = cpuRegs.cycle;
cpuRegs.eCycle[31] = 0;
// only set the next branch delta if the exception won't be handled for
// the current branch...
if( !eeEventTestIsActive )
cpuSetNextBranchDelta( 4 );
}
__forceinline void cpuTestTIMRInts() {
@ -711,11 +726,5 @@ void IntcpuBranchTest()
}
// fixme: why is this in the interpreter but not in the recompiler? (Air)
if (VU0.VI[REG_VPU_STAT].UL & 0x100) {
Cpu->ExecuteVU1Block();
}
g_EEFreezeRegs = true;
}

View File

@ -127,6 +127,7 @@ struct cpuRegisters {
extern s32 EEsCycle;
extern u32 EEoCycle;
extern bool eeEventTestIsActive;
extern PCSX2_ALIGNED16_DECL(cpuRegisters cpuRegs);
// used for optimization

View File

@ -128,7 +128,7 @@ void _SPR0interleave() {
CPU_INT(8, cycles);
}
void _dmaSPR0() {
static __forceinline void _dmaSPR0() {
if ((psHu32(DMAC_CTRL) & 0x30) == 0x20) { // STS == fromSPR

View File

@ -517,10 +517,6 @@ void SIO_FORCEINLINE sioInterrupt() {
void SaveState::sioFreeze() {
// eh, not supported anymore.. :)
//if( Mode == 0 && dwCurSaveStateVer == 0x7a30000e )
// savesize -= 4;
if( IsLoading() )
sio.count = 0;
Freeze( sio );

View File

@ -497,7 +497,8 @@ static void __fastcall PrintDebug(u8 value)
}
// fixme: this would be more optimal as a C++ template (with bit as the template parameter)
static __forceinline void ConstWrite_ExecTimer( uptr func, u8 index, u8 bit, int mmreg)
template< uint bit >
static void ConstWrite_ExecTimer( uptr func, u8 index, int mmreg)
{
if( bit != 32 )
{
@ -518,23 +519,23 @@ static __forceinline void ConstWrite_ExecTimer( uptr func, u8 index, u8 bit, int
}
#define CONSTWRITE_TIMERS(bit) \
case 0x10000000: ConstWrite_ExecTimer((uptr)&rcntWcount, 0, bit, mmreg); break; \
case 0x10000010: ConstWrite_ExecTimer((uptr)&rcntWmode, 0, bit, mmreg); break; \
case 0x10000020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 0, bit, mmreg); break; \
case 0x10000030: ConstWrite_ExecTimer((uptr)&rcntWhold, 0, bit, mmreg); break; \
case 0x10000000: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 0, mmreg); break; \
case 0x10000010: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 0, mmreg); break; \
case 0x10000020: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 0, mmreg); break; \
case 0x10000030: ConstWrite_ExecTimer<bit>((uptr)&rcntWhold, 0, mmreg); break; \
\
case 0x10000800: ConstWrite_ExecTimer((uptr)&rcntWcount, 1, bit, mmreg); break; \
case 0x10000810: ConstWrite_ExecTimer((uptr)&rcntWmode, 1, bit, mmreg); break; \
case 0x10000820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 1, bit, mmreg); break; \
case 0x10000830: ConstWrite_ExecTimer((uptr)&rcntWhold, 1, bit, mmreg); break; \
case 0x10000800: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 1, mmreg); break; \
case 0x10000810: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 1, mmreg); break; \
case 0x10000820: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 1, mmreg); break; \
case 0x10000830: ConstWrite_ExecTimer<bit>((uptr)&rcntWhold, 1, mmreg); break; \
\
case 0x10001000: ConstWrite_ExecTimer((uptr)&rcntWcount, 2, bit, mmreg); break; \
case 0x10001010: ConstWrite_ExecTimer((uptr)&rcntWmode, 2, bit, mmreg); break; \
case 0x10001020: ConstWrite_ExecTimer((uptr)&rcntWtarget, 2, bit, mmreg); break; \
case 0x10001000: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 2, mmreg); break; \
case 0x10001010: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 2, mmreg); break; \
case 0x10001020: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 2, mmreg); break; \
\
case 0x10001800: ConstWrite_ExecTimer((uptr)&rcntWcount, 3, bit, mmreg); break; \
case 0x10001810: ConstWrite_ExecTimer((uptr)&rcntWmode, 3, bit, mmreg); break; \
case 0x10001820: ConstWrite_ExecTimer((uptr)&rcntWtarget, 3, bit, mmreg); break; \
case 0x10001800: ConstWrite_ExecTimer<bit>((uptr)&rcntWcount, 3, mmreg); break; \
case 0x10001810: ConstWrite_ExecTimer<bit>((uptr)&rcntWmode, 3, mmreg); break; \
case 0x10001820: ConstWrite_ExecTimer<bit>((uptr)&rcntWtarget, 3, mmreg); break; \
void hwConstWrite8(u32 mem, int mmreg)
{
@ -971,11 +972,10 @@ void hwConstWrite32(u32 mem, int mmreg)
_eeMoveMMREGtoR(EAX, mmreg);
iFlushCall(0);
MOV32RtoR(ECX, EAX);
NOT32R(ECX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
SHR32ItoR(EAX, 16);
NOT32R(ECX);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
CALLFunc((uptr)cpuTestDMACInts);
break;
@ -1164,11 +1164,11 @@ void hwConstWrite64(u32 mem, int mmreg)
iFlushCall(0);
MOV32RtoR(ECX, EAX);
SHR32ItoR(EAX, 16);
NOT32R(ECX);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
AND16RtoM((uptr)&PS2MEM_HW[0xe010], ECX);
SHR32ItoR(EAX, 16);
XOR16RtoM((uptr)&PS2MEM_HW[0xe012], EAX);
CALLFunc((uptr)cpuTestDMACInts);
break;

View File

@ -610,8 +610,21 @@ void psxHwConstWrite16(u32 add, int mmreg) {
_eeWriteConstMem16((uptr)&sio.BaudReg, mmreg);
return;
case 0x1f801070:
_eeWriteConstMem16OP((uptr)&psxH[(add) & 0xffff], mmreg, 0);
case 0x1f801070:
_eeWriteConstMem16OP((uptr)&psxHu32(0x1070), mmreg, 0); // AND operation
return;
case 0x1f801074:
_eeWriteConstMem16((uptr)&psxHu32(0x1074), mmreg);
iFlushCall(0);
CALLFunc( (uptr)&iopTestIntc );
return;
case 0x1f801078:
//According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p
_eeWriteConstMem16((uptr)&psxHu32(0x1078), mmreg);
iFlushCall(0);
CALLFunc( (uptr)&iopTestIntc );
return;
// counters[0]
@ -807,7 +820,20 @@ void psxHwConstWrite32(u32 add, int mmreg)
return;
case 0x1f801070:
_eeWriteConstMem32OP((uptr)&psxH[(add) & 0xffff], mmreg, 0); // and
_eeWriteConstMem32OP((uptr)&psxHu32(0x1070), mmreg, 0); // and
return;
case 0x1f801074:
_eeWriteConstMem32((uptr)&psxHu32(0x1074), mmreg);
iFlushCall(0);
CALLFunc( (uptr)&iopTestIntc );
return;
case 0x1f801078:
//According to pSXAuthor this allways becomes 1 on write, but MHPB won't boot if value is not writen ;p
_eeWriteConstMem32((uptr)&psxHu32(0x1078), mmreg);
iFlushCall(0);
CALLFunc( (uptr)&iopTestIntc );
return;
// case 0x1f801088:
@ -1123,7 +1149,7 @@ int psxHw4ConstRead8(u32 x86reg, u32 add, u32 sign) {
case 0x1f402039: CONSTREAD8_CALL((uptr)cdvdRead39); return 1;
case 0x1f40203A: CONSTREAD8_CALL((uptr)cdvdRead3A); return 1;
default:
SysPrintf("*Unknown 8bit read at address %lx\n", add);
Console::Notice("*Unknown 8bit read at address %lx\n", add);
XOR32RtoR(x86reg, x86reg);
return 0;
}
@ -1147,7 +1173,7 @@ void psxHw4ConstWrite8(u32 add, int mmreg) {
case 0x1f402018: CONSTWRITE_CALL(cdvdWrite18); return;
case 0x1f40203A: CONSTWRITE_CALL(cdvdWrite3A); return;
default:
SysPrintf("*Unknown 8bit write at address %lx\n", add);
Console::Notice("*Unknown 8bit write at address %lx\n", add);
return;
}
}

View File

@ -1761,6 +1761,11 @@ void rpsxRFE()
SHR32ItoR(ECX, 2);
OR32RtoR (EAX, ECX);
MOV32RtoM((uptr)&psxRegs.CP0.n.Status, EAX);
// Test the IOP's INTC status, so that any pending ints get raised.
_psxFlushCall(0);
CALLFunc( (uptr)&iopTestIntc );
}
// R3000A tables