fix some ipc fifo bugs (fixes Defc0n-Zero demo and some recent libnds fifosystem changes)

This commit is contained in:
zeromus 2010-12-01 08:08:52 +00:00
parent fde699f8d9
commit be8b6906c8
5 changed files with 63 additions and 45 deletions

View File

@ -26,8 +26,7 @@
#include "gfx3d.h" #include "gfx3d.h"
// ========================================================= IPC FIFO // ========================================================= IPC FIFO
IPC_FIFO ipc_fifo[2]; // 0 - ARM9 IPC_FIFO ipc_fifo[2];
// 1 - ARM7
void IPC_FIFOinit(u8 proc) void IPC_FIFOinit(u8 proc)
{ {
@ -69,6 +68,9 @@ void IPC_FIFOsend(u8 proc, u32 val)
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r); T1WriteWord(MMU.MMU_MEM[proc_remote][0x40], 0x184, cnt_r);
if(cnt_r&IPCFIFOCNT_RECVIRQEN)
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
NDS_Reschedule(); NDS_Reschedule();
} }
@ -99,12 +101,14 @@ u32 IPC_FIFOrecv(u8 proc)
//LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n", //LOG("IPC%s recv FIFO 0x%08X size %03i (l 0x%X, tail %02i) (r 0x%X, tail %02i)\n",
// proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail); // proc?"7":"9", val, ipc_fifo[proc].size, cnt_l, ipc_fifo[proc].tail, cnt_r, ipc_fifo[proc^1].tail);
if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty if ( ipc_fifo[proc_remote].size == 0 ) // FIFO empty
{ {
cnt_l |= 0x0101; cnt_l |= 0x0100;
cnt_r |= 0x0001; cnt_r |= 0x0001;
if(cnt_r&IPCFIFOCNT_SENDIRQEN)
NDS_makeIrq(proc_remote, IRQ_BIT_IPCFIFO_SENDEMPTY);
} }
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
@ -117,6 +121,7 @@ u32 IPC_FIFOrecv(u8 proc)
void IPC_FIFOcnt(u8 proc, u16 val) void IPC_FIFOcnt(u8 proc, u16 val)
{ {
u8 proc_remote = proc ^ 1;
u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184); u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
@ -131,14 +136,24 @@ void IPC_FIFOcnt(u8 proc, u16 val)
ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0; ipc_fifo[proc].head = 0; ipc_fifo[proc].tail = 0; ipc_fifo[proc].size = 0;
cnt_l |= IPCFIFOCNT_SENDEMPTY; cnt_l |= IPCFIFOCNT_SENDEMPTY;
cnt_l &= ~IPCFIFOCNT_SENDFULL;
cnt_r |= IPCFIFOCNT_RECVEMPTY; cnt_r |= IPCFIFOCNT_RECVEMPTY;
cnt_l &= ~IPCFIFOCNT_SENDFULL;
cnt_r &= ~IPCFIFOCNT_RECVFULL; cnt_r &= ~IPCFIFOCNT_RECVFULL;
}
}
cnt_l &= ~IPCFIFOCNT_WRITEABLE; cnt_l &= ~IPCFIFOCNT_WRITEABLE;
cnt_l |= val & IPCFIFOCNT_WRITEABLE; cnt_l |= val & IPCFIFOCNT_WRITEABLE;
//IPCFIFOCNT_SENDIRQEN may have been set (and/or the fifo may have been cleared) so we may need to trigger this irq
//(this approach is used by libnds fifo system on occasion in fifoInternalSend, and began happening frequently for value32 with r4326)
if(cnt_l&IPCFIFOCNT_SENDIRQEN) if(cnt_l & IPCFIFOCNT_SENDEMPTY)
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_SENDEMPTY);
//IPCFIFOCNT_RECVIRQEN may have been set so we may need to trigger this irq
if(cnt_l&IPCFIFOCNT_RECVIRQEN) if(!(cnt_l & IPCFIFOCNT_RECVEMPTY))
NDS_makeIrq(proc, IRQ_BIT_IPCFIFO_RECVNONEMPTY);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);

View File

@ -1212,16 +1212,19 @@ static void validateIF_arm9()
template<int PROCNUM> static void REG_IF_WriteByte(u32 addr, u8 val) template<int PROCNUM> static void REG_IF_WriteByte(u32 addr, u8 val)
{ {
//the following bits are generated from logic and should not be affected here //the following bits are generated from logic and should not be affected here
//Bit 17 IPC Send FIFO Empty
//Bit 18 IPC Recv FIFO Not Empty
//Bit 21 NDS9 only: Geometry Command FIFO //Bit 21 NDS9 only: Geometry Command FIFO
//arm9: IF &= ~0x00260000; //arm9: IF &= ~0x00200000;
//arm7: IF &= ~0x00060000; //arm7: IF &= ~0x00000000;
//UPDATE IN setIF() ALSO!!!!!!!!!!!!!!!!
//UPDATE IN mmu_loadstate ALSO!!!!!!!!!!!!
if(addr==2) if(addr==2)
if(PROCNUM==ARMCPU_ARM9) if(PROCNUM==ARMCPU_ARM9)
val &= ~0x26; val &= ~0x20;
else else
val &= ~0x06; val &= ~0x00;
//ZERO 01-dec-2010 : I am no longer sure this approach is correct.. it proved to be wrong for IPC fifo.......
//it seems as if IF bits should always be cached (only the user can clear them)
MMU.reg_IF_bits[PROCNUM] &= (~(((u32)val)<<(addr<<3))); MMU.reg_IF_bits[PROCNUM] &= (~(((u32)val)<<(addr<<3)));
NDS_Reschedule(); NDS_Reschedule();
@ -1267,16 +1270,6 @@ u32 MMU_struct::gen_IF()
} }
} }
//generate IPC IF states from the ipc registers
u16 ipc = T1ReadWord(MMU.MMU_MEM[PROCNUM][0x40], 0x184);
if(ipc&IPCFIFOCNT_FIFOENABLE)
{
if(ipc&IPCFIFOCNT_SENDIRQEN) if(ipc&IPCFIFOCNT_SENDEMPTY)
IF |= IRQ_MASK_IPCFIFO_SENDEMPTY;
if(ipc&IPCFIFOCNT_RECVIRQEN) if(!(ipc&IPCFIFOCNT_RECVEMPTY))
IF |= IRQ_MASK_IPCFIFO_RECVNONEMPTY;
}
return IF; return IF;
} }
@ -1435,6 +1428,10 @@ static INLINE void MMU_IPCSync(u8 proc, u32 val)
if ((sync_l & 0x2000) && (sync_r & 0x4000)) if ((sync_l & 0x2000) && (sync_r & 0x4000))
setIF(proc^1, ( 1 << 16 )); setIF(proc^1, ( 1 << 16 ));
NDS_Reschedule();
} }
static INLINE u16 read_timer(int proc, int timerIndex) static INLINE u16 read_timer(int proc, int timerIndex)
@ -2643,13 +2640,13 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
case REG_IF: REG_IF_WriteWord<ARMCPU_ARM9>(0,val); return; case REG_IF: REG_IF_WriteWord<ARMCPU_ARM9>(0,val); return;
case REG_IF+2: REG_IF_WriteWord<ARMCPU_ARM9>(2,val); return; case REG_IF+2: REG_IF_WriteWord<ARMCPU_ARM9>(2,val); return;
case REG_IPCSYNC : case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM9, val); MMU_IPCSync(ARMCPU_ARM9, val);
return;
case REG_IPCFIFOCNT:
IPC_FIFOcnt(ARMCPU_ARM9, val);
return; return;
case REG_IPCFIFOCNT :
IPC_FIFOcnt(ARMCPU_ARM9, val);
return;
case REG_TM0CNTL : case REG_TM0CNTL :
case REG_TM1CNTL : case REG_TM1CNTL :
case REG_TM2CNTL : case REG_TM2CNTL :
@ -3094,17 +3091,18 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return; return;
} }
case REG_SQRTPARAM+4 : case REG_SQRTPARAM+4 :
{
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2BC, val); T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2BC, val);
execsqrt(); execsqrt();
return; return;
}
case REG_IPCSYNC : case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM9, val); MMU_IPCSync(ARMCPU_ARM9, val);
return; return;
case REG_IPCFIFOCNT:
case REG_IPCFIFOSEND : IPC_FIFOcnt(ARMCPU_ARM9, val);
IPC_FIFOsend(ARMCPU_ARM9, val); return;
case REG_IPCFIFOSEND:
IPC_FIFOsend(ARMCPU_ARM9, val);
return; return;
@ -3840,13 +3838,13 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
case REG_IF: REG_IF_WriteWord<ARMCPU_ARM7>(0,val); return; case REG_IF: REG_IF_WriteWord<ARMCPU_ARM7>(0,val); return;
case REG_IF+2: REG_IF_WriteWord<ARMCPU_ARM7>(2,val); return; case REG_IF+2: REG_IF_WriteWord<ARMCPU_ARM7>(2,val); return;
case REG_IPCSYNC : case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM7, val); MMU_IPCSync(ARMCPU_ARM7, val);
return; return;
case REG_IPCFIFOCNT:
case REG_IPCFIFOCNT :
IPC_FIFOcnt(ARMCPU_ARM7, val); IPC_FIFOcnt(ARMCPU_ARM7, val);
return; return;
case REG_TM0CNTL : case REG_TM0CNTL :
case REG_TM1CNTL : case REG_TM1CNTL :
case REG_TM2CNTL : case REG_TM2CNTL :
@ -3941,12 +3939,14 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
} }
case REG_IPCSYNC : case REG_IPCSYNC:
MMU_IPCSync(ARMCPU_ARM7, val); MMU_IPCSync(ARMCPU_ARM7, val);
return; return;
case REG_IPCFIFOCNT:
case REG_IPCFIFOSEND : IPC_FIFOcnt(ARMCPU_ARM7, val);
IPC_FIFOsend(ARMCPU_ARM7, val); return;
case REG_IPCFIFOSEND:
IPC_FIFOsend(ARMCPU_ARM7, val);
return; return;
case REG_GCROMCTRL : case REG_GCROMCTRL :

View File

@ -260,7 +260,7 @@ extern armcpu_t NDS_ARM9;
static INLINE void setIF(int PROCNUM, u32 flag) static INLINE void setIF(int PROCNUM, u32 flag)
{ {
//don't set generated bits!!! //don't set generated bits!!!
assert(!(flag&0x00260000)); assert(!(flag&0x00200000));
MMU.reg_IF_bits[PROCNUM] |= flag; MMU.reg_IF_bits[PROCNUM] |= flag;

View File

@ -358,6 +358,9 @@
#define IPCFIFOCNT_FIFOENABLE 0x8000 #define IPCFIFOCNT_FIFOENABLE 0x8000
#define IPCFIFOCNT_WRITEABLE (IPCFIFOCNT_SENDIRQEN | IPCFIFOCNT_RECVIRQEN | IPCFIFOCNT_FIFOENABLE) #define IPCFIFOCNT_WRITEABLE (IPCFIFOCNT_SENDIRQEN | IPCFIFOCNT_RECVIRQEN | IPCFIFOCNT_FIFOENABLE)
#define IPCSYNC_IRQ_SEND 0x2000
#define IPCSYNC_IRQ_RECV 0x4000
#define IRQ_BIT_LCD_VBLANK 0 #define IRQ_BIT_LCD_VBLANK 0
#define IRQ_BIT_LCD_HBLANK 1 #define IRQ_BIT_LCD_HBLANK 1
#define IRQ_BIT_LCD_VMATCH 2 #define IRQ_BIT_LCD_VMATCH 2

View File

@ -448,8 +448,8 @@ static bool mmu_loadstate(EMUFILE* is, int size)
ok &= MMU_new.div.loadstate(is,version); ok &= MMU_new.div.loadstate(is,version);
//to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated //to prevent old savestates from confusing IF bits, mask out ones which had been stored but should have been generated
MMU.reg_IF_bits[0] &= ~0x00260000; MMU.reg_IF_bits[0] &= ~0x00200000;
MMU.reg_IF_bits[1] &= ~0x00060000; MMU.reg_IF_bits[1] &= ~0x00000000;
MMU_new.gxstat.fifo_low = gxFIFO.size <= 127; MMU_new.gxstat.fifo_low = gxFIFO.size <= 127;
MMU_new.gxstat.fifo_empty = gxFIFO.size == 0; MMU_new.gxstat.fifo_empty = gxFIFO.size == 0;