see, Arisotura, was it that hard? blarg.

This commit is contained in:
Arisotura 2021-08-31 01:40:23 +02:00
parent 43223f0a90
commit 79fa4200b7
2 changed files with 160 additions and 246 deletions

View File

@ -78,6 +78,7 @@ void DMA::Reset()
Running = false; Running = false;
InProgress = false; InProgress = false;
MRAMBurstCount = 0;
} }
void DMA::DoSavestate(Savestate* file) void DMA::DoSavestate(Savestate* file)
@ -101,6 +102,7 @@ void DMA::DoSavestate(Savestate* file)
file->Var32(&Running); file->Var32(&Running);
file->Bool32(&InProgress); file->Bool32(&InProgress);
file->Bool32(&IsGXFIFODMA); file->Bool32(&IsGXFIFODMA);
file->Var32(&MRAMBurstCount);
} }
void DMA::WriteCnt(u32 val) void DMA::WriteCnt(u32 val)
@ -178,10 +180,7 @@ void DMA::Start()
// TODO eventually: not stop if we're running code in ITCM // TODO eventually: not stop if we're running code in ITCM
/*if (NDS::DMAsRunning(CPU)) Running = 2;
Running = 1;
else*/
Running = 2;
// safety measure // safety measure
MRAMBurstTable = DMATiming::MRAMDummy; MRAMBurstTable = DMATiming::MRAMDummy;
@ -190,72 +189,6 @@ void DMA::Start()
NDS::StopCPU(CPU, 1<<Num); NDS::StopCPU(CPU, 1<<Num);
} }
void DMA::CalculateTimings(u32& burststart, u32& unit)
{
// DMA timing rules:
// * for an incrementing address: first access (in burst) is nonseq, following ones are seq, maximum burst length is 118 units
// * for a fixed/decrementing address: all accesses are nonseq
// * reads from mainRAM take one less cycle when at the end of a 32-byte block
u32 src_n, src_s, dst_n, dst_s;
bool src_mainram, sameregion;
if (CPU == 0)
{
u32 src_id = CurSrcAddr >> 14;
u32 dst_id = CurDstAddr >> 14;
if (Cnt & (1<<26)) // 32-bit
{
src_n = NDS::ARM9MemTimings[src_id][6];
src_s = NDS::ARM9MemTimings[src_id][7];
dst_n = NDS::ARM9MemTimings[dst_id][6];
dst_s = NDS::ARM9MemTimings[dst_id][7];
}
else // 16-bit
{
src_n = NDS::ARM9MemTimings[src_id][4];
src_s = NDS::ARM9MemTimings[src_id][5];
dst_n = NDS::ARM9MemTimings[dst_id][4];
dst_s = NDS::ARM9MemTimings[dst_id][5];
}
u32 src_rgn = NDS::ARM9Regions[src_id];
u32 dst_rgn = NDS::ARM9Regions[dst_id];
src_mainram = (src_rgn == NDS::Mem9_MainRAM);
sameregion = ((src_rgn & dst_rgn) != 0);
}
else
{
u32 src_id = CurSrcAddr >> 15;
u32 dst_id = CurDstAddr >> 15;
if (Cnt & (1<<26)) // 32-bit
{
src_n = NDS::ARM7MemTimings[src_id][2];
src_s = NDS::ARM7MemTimings[src_id][3];
dst_n = NDS::ARM7MemTimings[dst_id][2];
dst_s = NDS::ARM7MemTimings[dst_id][3];
}
else // 16-bit
{
src_n = NDS::ARM7MemTimings[src_id][0];
src_s = NDS::ARM7MemTimings[src_id][1];
dst_n = NDS::ARM7MemTimings[dst_id][0];
dst_s = NDS::ARM7MemTimings[dst_id][1];
}
u32 src_rgn = NDS::ARM7Regions[src_id];
u32 dst_rgn = NDS::ARM7Regions[dst_id];
src_mainram = (src_rgn == NDS::Mem7_MainRAM);
sameregion = ((src_rgn & dst_rgn) != 0);
}
//
}
u32 DMA::UnitTimings9_16(bool burststart) u32 DMA::UnitTimings9_16(bool burststart)
{ {
u32 src_id = CurSrcAddr >> 14; u32 src_id = CurSrcAddr >> 14;
@ -430,87 +363,184 @@ u32 DMA::UnitTimings9_32(bool burststart)
else else
return src_s + dst_s; return src_s + dst_s;
} }
}
#if 0 // TODO: the ARM7 ones don't take into account that the two wifi regions have different timings
if (src_rgn & dst_rgn)
u32 DMA::UnitTimings7_16(bool burststart)
{
u32 src_id = CurSrcAddr >> 15;
u32 dst_id = CurDstAddr >> 15;
u32 src_rgn = NDS::ARM7Regions[src_id];
u32 dst_rgn = NDS::ARM7Regions[dst_id];
u32 src_n, src_s, dst_n, dst_s;
src_n = NDS::ARM7MemTimings[src_id][0];
src_s = NDS::ARM7MemTimings[src_id][1];
dst_n = NDS::ARM7MemTimings[dst_id][0];
dst_s = NDS::ARM7MemTimings[dst_id][1];
if (src_rgn == NDS::Mem7_MainRAM)
{ {
return src_n + dst_n; if (dst_rgn == NDS::Mem7_MainRAM)
} return 16;
u32 ret = 0;
ret=1;
if (src_rgn == NDS::Mem9_MainRAM)
{
// for main RAM: sequential timings only work with incrementing addresses
// read bursts have a maximum length of 118 words
if (SrcAddrInc > 0) if (SrcAddrInc > 0)
{ {
if (burststart || BurstCount >= 118) if (burststart || MRAMBurstTable[MRAMBurstCount] == 0)
BurstCount = 0; {
MRAMBurstCount = 0;
ret += (BurstCount == 0) ? src_n : src_s; if (dst_rgn == NDS::Mem7_GBAROM || dst_rgn == NDS::Mem7_Wifi0 || dst_rgn == NDS::Mem7_Wifi1)
{
if (dst_s == 4)
MRAMBurstTable = DMATiming::MRAMRead16Bursts[1];
else
MRAMBurstTable = DMATiming::MRAMRead16Bursts[2];
}
else
MRAMBurstTable = DMATiming::MRAMRead16Bursts[0];
}
BurstCount++; u32 ret = MRAMBurstTable[MRAMBurstCount++];
return ret;
} }
else else
{ {
ret += src_n; // TODO: not quite right for GBA slot
if ((CurSrcAddr & 0x1F) == 0x1C) ret--; return (((CurSrcAddr & 0x1F) == 0x1E) ? 7 : 8) +
(burststart ? dst_n : dst_s);
} }
// main RAM reads can parallelize with writes to another region
ret--;
} }
else if (src_rgn == NDS::Mem9_GBAROM) else if (dst_rgn == NDS::Mem7_MainRAM)
{ {
// for GBA ROM: sequential timings always work, except for the last halfword
// of every 0x20000 byte block
ret += (burststart || ((CurSrcAddr & 0x1FFFF) == 0x1FFFC)) ? src_n : src_s;
}
else
{
// for other regions: nonseq/sequential timings are the same
ret += src_s;
}
if (dst_rgn == NDS::Mem9_MainRAM)
{
// for main RAM: sequential timings only work with incrementing addresses
// write bursts have a maximum length of 80 words
if (DstAddrInc > 0) if (DstAddrInc > 0)
{ {
if (burststart || BurstCount >= 80) if (burststart || MRAMBurstTable[MRAMBurstCount] == 0)
BurstCount = 0; {
MRAMBurstCount = 0;
ret += (BurstCount == 0) ? dst_n : dst_s; if (src_rgn == NDS::Mem7_GBAROM || src_rgn == NDS::Mem7_Wifi0 || src_rgn == NDS::Mem7_Wifi1)
{
if (src_s == 4)
MRAMBurstTable = DMATiming::MRAMWrite16Bursts[1];
else
MRAMBurstTable = DMATiming::MRAMWrite16Bursts[2];
}
else
MRAMBurstTable = DMATiming::MRAMWrite16Bursts[0];
}
BurstCount++; u32 ret = MRAMBurstTable[MRAMBurstCount++];
return ret;
} }
else else
{ {
ret += dst_n; return (burststart ? src_n : src_s) + 7;
} }
} }
else if (dst_rgn == NDS::Mem9_GBAROM) else if (src_rgn & dst_rgn)
{ {
// for GBA ROM: sequential timings always work, except for the last halfword return src_n + dst_n + 1;
// of every 0x20000 byte block
ret += (burststart || ((CurDstAddr & 0x1FFFF) == 0x1FFFC)) ? dst_n : dst_s;
} }
else else
{ {
// for other regions: nonseq/sequential timings are the same if (burststart)
return src_n + dst_n;
ret += dst_s; else
return src_s + dst_s;
}
}
u32 DMA::UnitTimings7_32(bool burststart)
{
u32 src_id = CurSrcAddr >> 15;
u32 dst_id = CurDstAddr >> 15;
u32 src_rgn = NDS::ARM7Regions[src_id];
u32 dst_rgn = NDS::ARM7Regions[dst_id];
u32 src_n, src_s, dst_n, dst_s;
src_n = NDS::ARM7MemTimings[src_id][2];
src_s = NDS::ARM7MemTimings[src_id][3];
dst_n = NDS::ARM7MemTimings[dst_id][2];
dst_s = NDS::ARM7MemTimings[dst_id][3];
if (src_rgn == NDS::Mem7_MainRAM)
{
if (dst_rgn == NDS::Mem7_MainRAM)
return 18;
if (SrcAddrInc > 0)
{
if (burststart || MRAMBurstTable[MRAMBurstCount] == 0)
{
MRAMBurstCount = 0;
if (dst_rgn == NDS::Mem7_GBAROM || dst_rgn == NDS::Mem7_Wifi0 || dst_rgn == NDS::Mem7_Wifi1)
{
if (dst_s == 8)
MRAMBurstTable = DMATiming::MRAMRead32Bursts[2];
else
MRAMBurstTable = DMATiming::MRAMRead32Bursts[3];
}
else if (dst_n == 2)
MRAMBurstTable = DMATiming::MRAMRead32Bursts[0];
else
MRAMBurstTable = DMATiming::MRAMRead32Bursts[1];
}
u32 ret = MRAMBurstTable[MRAMBurstCount++];
return ret;
}
else
{
// TODO: not quite right for GBA slot
return (((CurSrcAddr & 0x1F) == 0x1C) ? (dst_n==2 ? 7:8) : 9) +
(burststart ? dst_n : dst_s);
}
}
else if (dst_rgn == NDS::Mem7_MainRAM)
{
if (DstAddrInc > 0)
{
if (burststart || MRAMBurstTable[MRAMBurstCount] == 0)
{
MRAMBurstCount = 0;
if (src_rgn == NDS::Mem7_GBAROM || src_rgn == NDS::Mem7_Wifi0 || src_rgn == NDS::Mem7_Wifi1)
{
if (src_s == 8)
MRAMBurstTable = DMATiming::MRAMWrite32Bursts[2];
else
MRAMBurstTable = DMATiming::MRAMWrite32Bursts[3];
}
else if (src_n == 2)
MRAMBurstTable = DMATiming::MRAMWrite32Bursts[0];
else
MRAMBurstTable = DMATiming::MRAMWrite32Bursts[1];
}
u32 ret = MRAMBurstTable[MRAMBurstCount++];
return ret;
}
else
{
return (burststart ? src_n : src_s) + 8;
}
}
else if (src_rgn & dst_rgn)
{
return src_n + dst_n + 1;
}
else
{
if (burststart)
return src_n + dst_n;
else
return src_s + dst_s;
} }
#endif
// return ret;
} }
template <int ConsoleType> template <int ConsoleType>
@ -524,34 +554,10 @@ void DMA::Run9()
bool burststart = (Running == 2); bool burststart = (Running == 2);
Running = 1; Running = 1;
s32 unitcycles;
//s32 lastcycles = cycles;
if (!(Cnt & (1<<26))) if (!(Cnt & (1<<26)))
{ {
#if 1
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
{
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][0] + NDS::ARM9MemTimings[CurDstAddr >> 14][0];
}
else
{
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][1] + NDS::ARM9MemTimings[CurDstAddr >> 14][1];
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
unitcycles++;
/*if (burststart)
{
cycles -= 2;
cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][0] + NDS::ARM9MemTimings[CurDstAddr >> 14][0]);
cycles += unitcycles;
}*/
}
#endif
while (IterCount > 0 && !Stall) while (IterCount > 0 && !Stall)
{ {
//NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift);
NDS::ARM9Timestamp += (UnitTimings9_16(burststart) << NDS::ARM9ClockShift); NDS::ARM9Timestamp += (UnitTimings9_16(burststart) << NDS::ARM9ClockShift);
burststart = false; burststart = false;
@ -570,50 +576,8 @@ void DMA::Run9()
} }
else else
{ {
#if 0
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
{
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2];
}
else
{
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][3] + NDS::ARM9MemTimings[CurDstAddr >> 14][3];
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
unitcycles++;
else if ((CurSrcAddr >> 24) == 0x02)
unitcycles--;
/*if (burststart)
{
cycles -= 2;
cycles -= (NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2]);
cycles += unitcycles;
}*/
}
#endif
/*bool forcedNS = false;
if (((Cnt >> 21) & 0xF) != 0x0) forcedNS = true;
if (NDS::ARM9Regions[CurSrcAddr >> 14] & NDS::ARM9Regions[CurDstAddr >> 14]) forcedNS = true;
if (burststart || forcedNS)
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][6] + NDS::ARM9MemTimings[CurDstAddr >> 14][6];
else
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][7] + NDS::ARM9MemTimings[CurDstAddr >> 14][7];*/
bool sameregion = (NDS::ARM9Regions[CurSrcAddr >> 14] & NDS::ARM9Regions[CurDstAddr >> 14]) != 0;
if (burststart || sameregion || ((Cnt >> 23) & 0x3) != 0)
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][6];
else
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][7];
if (burststart || sameregion || ((Cnt >> 21) & 0x3) != 0)
unitcycles += NDS::ARM9MemTimings[CurDstAddr >> 14][6];
else
unitcycles += NDS::ARM9MemTimings[CurDstAddr >> 14][7];
if (!sameregion) unitcycles--; // ???
// 6 not good?? (all 10, not 9)
// src-fixed is slower??
while (IterCount > 0 && !Stall) while (IterCount > 0 && !Stall)
{ {
//NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift);
NDS::ARM9Timestamp += (UnitTimings9_32(burststart) << NDS::ARM9ClockShift); NDS::ARM9Timestamp += (UnitTimings9_32(burststart) << NDS::ARM9ClockShift);
burststart = false; burststart = false;
@ -628,17 +592,6 @@ void DMA::Run9()
RemCount--; RemCount--;
if (NDS::ARM9Timestamp >= NDS::ARM9Target) break; if (NDS::ARM9Timestamp >= NDS::ARM9Target) break;
//bool sameregion = (NDS::ARM9Regions[CurSrcAddr >> 14] & NDS::ARM9Regions[CurDstAddr >> 14]) != 0;
if (sameregion || ((Cnt >> 23) & 0x3) != 0)
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][6];
else
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][7];
if (sameregion || ((Cnt >> 21) & 0x3) != 0)
unitcycles += NDS::ARM9MemTimings[CurDstAddr >> 14][6];
else
unitcycles += NDS::ARM9MemTimings[CurDstAddr >> 14][7];
if (!sameregion) unitcycles--; // ???
} }
} }
@ -681,32 +634,12 @@ void DMA::Run7()
bool burststart = (Running == 2); bool burststart = (Running == 2);
Running = 1; Running = 1;
s32 unitcycles;
//s32 lastcycles = cycles;
if (!(Cnt & (1<<26))) if (!(Cnt & (1<<26)))
{ {
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
{
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][0] + NDS::ARM7MemTimings[CurDstAddr >> 15][0];
}
else
{
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][1] + NDS::ARM7MemTimings[CurDstAddr >> 15][1];
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
unitcycles++;
/*if (burststart)
{
cycles -= 2;
cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][0] + NDS::ARM7MemTimings[CurDstAddr >> 15][0]);
cycles += unitcycles;
}*/
}
while (IterCount > 0 && !Stall) while (IterCount > 0 && !Stall)
{ {
NDS::ARM7Timestamp += unitcycles; NDS::ARM7Timestamp += UnitTimings7_16(burststart);
burststart = false;
if (ConsoleType == 1) if (ConsoleType == 1)
DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr)); DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr));
@ -723,29 +656,10 @@ void DMA::Run7()
} }
else else
{ {
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
{
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2];
}
else
{
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][3] + NDS::ARM7MemTimings[CurDstAddr >> 15][3];
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
unitcycles++;
else if ((CurSrcAddr >> 24) == 0x02)
unitcycles--;
/*if (burststart)
{
cycles -= 2;
cycles -= (NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2]);
cycles += unitcycles;
}*/
}
while (IterCount > 0 && !Stall) while (IterCount > 0 && !Stall)
{ {
NDS::ARM7Timestamp += unitcycles; NDS::ARM7Timestamp += UnitTimings7_32(burststart);
burststart = false;
if (ConsoleType == 1) if (ConsoleType == 1)
DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr)); DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr));

View File

@ -34,10 +34,10 @@ public:
void WriteCnt(u32 val); void WriteCnt(u32 val);
void Start(); void Start();
void CalculateTimings(u32& burststart, u32& unit);
u32 UnitTimings9_16(bool burststart); u32 UnitTimings9_16(bool burststart);
u32 UnitTimings9_32(bool burststart); u32 UnitTimings9_32(bool burststart);
u32 UnitTimings7_16(bool burststart);
u32 UnitTimings7_32(bool burststart);
template <int ConsoleType> template <int ConsoleType>
void Run(); void Run();