dmac: wrap source address to remain in 16K

Add some assertions of memcpy that overflow (need to be wrapped)
This commit is contained in:
Gregory Hainaut 2016-01-27 22:37:17 +01:00
parent c959424957
commit 5d1e5df205
2 changed files with 32 additions and 22 deletions

View File

@ -47,7 +47,7 @@ void __fastcall _hwWrite32( u32 mem, u32 value )
#if PSX_EXTRALOGS #if PSX_EXTRALOGS
if ((mem & 0x1000ff00) == 0x1000f300) DevCon.Warning("32bit Write to SIF Register %x value %x", mem, value); if ((mem & 0x1000ff00) == 0x1000f300) DevCon.Warning("32bit Write to SIF Register %x value %x", mem, value);
//if ((mem & 0x1000ff00) == 0x1000f200) DevCon.Warning("Write to SIF Register %x value %x", mem, value); //if ((mem & 0x1000ff00) == 0x1000f200) DevCon.Warning("Write to SIF Register %x value %x", mem, value);
#endif #endif
switch (page) switch (page)
{ {
case 0x00: if (!rcntWrite32<0x00>(mem, value)) return; break; case 0x00: if (!rcntWrite32<0x00>(mem, value)) return; break;
@ -131,7 +131,7 @@ void __fastcall _hwWrite32( u32 mem, u32 value )
case 0x0e: case 0x0e:
if (!dmacWrite32<page>(mem, value)) return; if (!dmacWrite32<page>(mem, value)) return;
break; break;
case 0x0f: case 0x0f:
{ {
switch( HELPSWITCH(mem) ) switch( HELPSWITCH(mem) )
@ -231,10 +231,10 @@ void __fastcall _hwWrite32( u32 mem, u32 value )
// (unhandled so fall through to default) // (unhandled so fall through to default)
} }
} }
break; break;
} }
psHu32(mem) = value; psHu32(mem) = value;
} }

View File

@ -34,10 +34,10 @@ static void TestClearVUs(u32 madr, u32 qwc, bool isWrite)
{ {
if (madr < 0x11004000) if (madr < 0x11004000)
{ {
if(isWrite == true) if(isWrite == true)
{ {
DbgCon.Warning("scratch pad clearing vu0"); DbgCon.Warning("scratch pad clearing vu0");
CpuVU0->Clear(madr&0xfff, qwc * 16); CpuVU0->Clear(madr&0xfff, qwc * 16);
} }
@ -47,8 +47,8 @@ static void TestClearVUs(u32 madr, u32 qwc, bool isWrite)
} }
} }
else if (madr >= 0x11008000 && madr < 0x1100c000) else if (madr >= 0x11008000 && madr < 0x1100c000)
{ {
if(isWrite == true) if(isWrite == true)
{ {
DbgCon.Warning("scratch pad clearing vu1"); DbgCon.Warning("scratch pad clearing vu1");
@ -87,16 +87,18 @@ int _SPR0chain()
spr0ch.madr += partialqwc << 4; spr0ch.madr += partialqwc << 4;
spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK); spr0ch.madr = dmacRegs.rbor.ADDR + (spr0ch.madr & dmacRegs.rbsr.RMSK);
spr0ch.sadr += partialqwc << 4; spr0ch.sadr += partialqwc << 4;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.qwc -= partialqwc; spr0ch.qwc -= partialqwc;
spr0finished = true; spr0finished = true;
} }
else else
{ {
//Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of //Taking an arbitary small value for games which like to check the QWC/MADR instead of STR, so get most of
//the cycle delay out of the way before the end. //the cycle delay out of the way before the end.
partialqwc = spr0ch.qwc; partialqwc = spr0ch.qwc;
pxAssertMsg((spr0ch.sadr + partialqwc*16) < 0x4000, "TODO: Copy must be wrapped");
memcpy(pMem, &psSu128(spr0ch.sadr), partialqwc*16); memcpy(pMem, &psSu128(spr0ch.sadr), partialqwc*16);
// clear VU mem also! // clear VU mem also!
@ -104,11 +106,12 @@ int _SPR0chain()
spr0ch.madr += partialqwc << 4; spr0ch.madr += partialqwc << 4;
spr0ch.sadr += partialqwc << 4; spr0ch.sadr += partialqwc << 4;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.qwc -= partialqwc; spr0ch.qwc -= partialqwc;
} }
return (partialqwc); // bus is 1/2 the ee speed return (partialqwc); // bus is 1/2 the ee speed
} }
@ -151,10 +154,12 @@ void _SPR0interleave()
case MFD_RESERVED: case MFD_RESERVED:
// clear VU mem also! // clear VU mem also!
TestClearVUs(spr0ch.madr, spr0ch.qwc, true); TestClearVUs(spr0ch.madr, spr0ch.qwc, true);
pxAssertMsg((spr0ch.sadr + spr0ch.qwc*16) < 0x4000, "TODO: Copy must be wrapped");
memcpy(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc*16); memcpy(pMem, &psSu128(spr0ch.sadr), spr0ch.qwc*16);
break; break;
} }
spr0ch.sadr += spr0ch.qwc * 16; spr0ch.sadr += spr0ch.qwc * 16;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.madr += (sqwc + spr0ch.qwc) * 16; spr0ch.madr += (sqwc + spr0ch.qwc) * 16;
} }
@ -194,6 +199,7 @@ static __fi void _dmaSPR0()
// Destination Chain Mode // Destination Chain Mode
ptag = (tDMA_TAG*)&psSu32(spr0ch.sadr); ptag = (tDMA_TAG*)&psSu32(spr0ch.sadr);
spr0ch.sadr += 16; spr0ch.sadr += 16;
spr0ch.sadr &= 0x3FFF; // Limited to 16K
spr0ch.unsafeTransfer(ptag); spr0ch.unsafeTransfer(ptag);
@ -251,8 +257,8 @@ static __fi void _dmaSPR0()
void SPRFROMinterrupt() void SPRFROMinterrupt()
{ {
if (!spr0finished || spr0ch.qwc > 0) if (!spr0finished || spr0ch.qwc > 0)
{ {
_dmaSPR0(); _dmaSPR0();
@ -284,7 +290,7 @@ void SPRFROMinterrupt()
break; break;
} }
} }
return; return;
} }
@ -300,10 +306,10 @@ void dmaSPR0() // fromSPR
SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx", SPR_LOG("dmaSPR0 chcr = %lx, madr = %lx, qwc = %lx, sadr = %lx",
spr0ch.chcr._u32, spr0ch.madr, spr0ch.qwc, spr0ch.sadr); spr0ch.chcr._u32, spr0ch.madr, spr0ch.qwc, spr0ch.sadr);
spr0finished = false; //Init spr0finished = false; //Init
if(spr0ch.chcr.MOD == CHAIN_MODE && spr0ch.qwc > 0) if(spr0ch.chcr.MOD == CHAIN_MODE && spr0ch.qwc > 0)
{ {
//DevCon.Warning(L"SPR0 QWC on Chain " + spr0ch.chcr.desc()); //DevCon.Warning(L"SPR0 QWC on Chain " + spr0ch.chcr.desc());
if (spr0ch.chcr.tag().ID == TAG_END) // but not TAG_REFE? if (spr0ch.chcr.tag().ID == TAG_END) // but not TAG_REFE?
@ -322,8 +328,10 @@ __fi static void SPR1transfer(const void* data, int qwc)
TestClearVUs(spr1ch.madr, spr1ch.qwc, false); TestClearVUs(spr1ch.madr, spr1ch.qwc, false);
} }
pxAssertMsg((spr1ch.sadr + qwc*16) < 0x4000, "TODO: Copy must be wrapped");
memcpy(&psSu128(spr1ch.sadr), data, qwc*16); memcpy(&psSu128(spr1ch.sadr), data, qwc*16);
spr1ch.sadr += qwc * 16; spr1ch.sadr += qwc * 16;
spr1ch.sadr &= 0x3FFF; // Limited to 16K
} }
@ -346,19 +354,19 @@ int _SPR1chain()
spr1ch.qwc -= partialqwc; spr1ch.qwc -= partialqwc;
hwDmacSrcTadrInc(spr1ch); hwDmacSrcTadrInc(spr1ch);
return (partialqwc); return (partialqwc);
} }
__fi void SPR1chain() __fi void SPR1chain()
{ {
int cycles = 0; int cycles = 0;
if(!CHECK_IPUWAITHACK) if(!CHECK_IPUWAITHACK)
{ {
cycles = _SPR1chain() * BIAS; cycles = _SPR1chain() * BIAS;
CPU_INT(DMAC_TO_SPR, cycles); CPU_INT(DMAC_TO_SPR, cycles);
} }
else else
{ {
_SPR1chain(); _SPR1chain();
CPU_INT(DMAC_TO_SPR, 8); CPU_INT(DMAC_TO_SPR, 8);
@ -381,8 +389,10 @@ void _SPR1interleave()
spr1ch.qwc = std::min(tqwc, qwc); spr1ch.qwc = std::min(tqwc, qwc);
qwc -= spr1ch.qwc; qwc -= spr1ch.qwc;
pMem = SPRdmaGetAddr(spr1ch.madr, false); pMem = SPRdmaGetAddr(spr1ch.madr, false);
pxAssertMsg((spr1ch.sadr + spr1ch.qwc*16) < 0x4000, "TODO: Copy must be wrapped");
memcpy(&psSu128(spr1ch.sadr), pMem, spr1ch.qwc*16); memcpy(&psSu128(spr1ch.sadr), pMem, spr1ch.qwc*16);
spr1ch.sadr += spr1ch.qwc * 16; spr1ch.sadr += spr1ch.qwc * 16;
spr1ch.sadr &= 0x3FFF; // Limited to 16K
spr1ch.madr += (sqwc + spr1ch.qwc) * 16; spr1ch.madr += (sqwc + spr1ch.qwc) * 16;
} }
@ -465,10 +475,10 @@ void dmaSPR1() // toSPR
" tadr = 0x%x, sadr = 0x%x", " tadr = 0x%x, sadr = 0x%x",
spr1ch.chcr._u32, spr1ch.madr, spr1ch.qwc, spr1ch.chcr._u32, spr1ch.madr, spr1ch.qwc,
spr1ch.tadr, spr1ch.sadr); spr1ch.tadr, spr1ch.sadr);
spr1finished = false; //Init spr1finished = false; //Init
if(spr1ch.chcr.MOD == CHAIN_MODE && spr1ch.qwc > 0) if(spr1ch.chcr.MOD == CHAIN_MODE && spr1ch.qwc > 0)
{ {
//DevCon.Warning(L"SPR1 QWC on Chain " + spr1ch.chcr.desc()); //DevCon.Warning(L"SPR1 QWC on Chain " + spr1ch.chcr.desc());
if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE) || (spr1ch.chcr.tag().IRQ && spr1ch.chcr.TIE)) if ((spr1ch.chcr.tag().ID == TAG_END) || (spr1ch.chcr.tag().ID == TAG_REFE) || (spr1ch.chcr.tag().IRQ && spr1ch.chcr.TIE))