Compare commits

..

1 Commits

Author SHA1 Message Date
Jakly fa80907056
Merge 98d0a6b371 into 7d718ada39 2024-12-20 15:42:43 +00:00
9 changed files with 252 additions and 518 deletions

View File

@ -1447,22 +1447,6 @@ void ARMv5::ForceInterlock_2()
NDS.ARM9Timestamp = TimestampMemory + ILForceDelay; NDS.ARM9Timestamp = TimestampMemory + ILForceDelay;
} }
void ARMv5::QueueFunction(void (ARMv5::*QueueEntry)(void))
{
if ((NDS.ARM9Timestamp >= NDS.ARM9Target) || (MRTrack.Type != MainRAMType::Null))
FuncQueue[FuncQueueFill++] = QueueEntry;
else
(this->*QueueEntry)();
}
void ARMv4::QueueFunction(void (ARMv4::*QueueEntry)(void))
{
if ((NDS.ARM7Timestamp >= NDS.ARM7Target) || (MRTrack.Type != MainRAMType::Null))
FuncQueue[FuncQueueFill++] = QueueEntry;
else
(this->*QueueEntry)();
}
void ARMv4::CodeRead16(u32 addr) void ARMv4::CodeRead16(u32 addr)
{ {
if ((addr >> 24) == 0x02) if ((addr >> 24) == 0x02)

View File

@ -724,7 +724,13 @@ public:
*/ */
u32 CP15Read(const u32 id) const; u32 CP15Read(const u32 id) const;
void QueueFunction(void (ARMv5::*QueueEntry)(void)); inline void QueueFunction(void (ARMv5::*QueueEntry)(void))
{
if (MRTrack.Type != MainRAMType::Null)
FuncQueue[FuncQueueFill++] = QueueEntry;
else
(this->*QueueEntry)();
}
// Queue Functions // Queue Functions
void StartExecARM(); void StartExecARM();
@ -738,47 +744,27 @@ public:
void JumpTo_3C(); void JumpTo_3C();
void JumpTo_4(); void JumpTo_4();
void CodeRead32_2(); void CodeRead32_2();
void CodeRead32_3();
void CodeRead32_4();
void ICacheLookup_2(); void ICacheLookup_2();
void DAbortHandle(); void DAbortHandle();
void DCacheFin8(); void DCacheFin8();
void DRead8_2(); void DRead8_2();
void DRead8_3(); void DRead8_3();
void DRead8_4();
void DRead8_5();
void DCacheFin16(); void DCacheFin16();
void DRead16_2(); void DRead16_2();
void DRead16_3(); void DRead16_3();
void DRead16_4();
void DRead16_5();
void DCacheFin32(); void DCacheFin32();
void DRead32_2(); void DRead32_2();
void DRead32_3(); void DRead32_3();
void DRead32_4();
void DRead32_5();
void DRead32S_2(); void DRead32S_2();
void DRead32S_3(); void DRead32S_3();
void DRead32S_4();
void DRead32S_5A();
void DRead32S_5B();
void DWrite8_2(); void DWrite8_2();
void DWrite8_3(); void DWrite8_3();
void DWrite8_4();
void DWrite8_5();
void DWrite16_2(); void DWrite16_2();
void DWrite16_3(); void DWrite16_3();
void DWrite16_4();
void DWrite16_5();
void DWrite32_2(); void DWrite32_2();
void DWrite32_3(); void DWrite32_3();
void DWrite32_4();
void DWrite32_5();
void DWrite32S_2(); void DWrite32S_2();
void DWrite32S_3(); void DWrite32S_3();
void DWrite32S_4();
void DWrite32S_5A();
void DWrite32S_5B();
void WBCheck_2(); void WBCheck_2();
void ICachePrefetch_2(); void ICachePrefetch_2();
void DCacheLookup_2(); void DCacheLookup_2();
@ -947,7 +933,13 @@ public:
void AddCycles_CDI() override; void AddCycles_CDI() override;
void AddCycles_CD() override; void AddCycles_CD() override;
void QueueFunction(void (ARMv4::*QueueEntry)(void)); inline void QueueFunction(void (ARMv4::*QueueEntry)(void))
{
if (MRTrack.Type != MainRAMType::Null)
FuncQueue[FuncQueueFill++] = QueueEntry;
else
(this->*QueueEntry)();
}
void StartExecARM(); void StartExecARM();
void StartExecTHUMB(); void StartExecTHUMB();

View File

@ -2214,12 +2214,6 @@ void ARMv5::CodeRead32(u32 addr)
#endif #endif
} }
FetchAddr[16] = addr;
QueueFunction(&ARMv5::CodeRead32_2);
}
void ARMv5::CodeRead32_2()
{
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp; if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with dcache streaming by 6 cycles // bus reads can only overlap with dcache streaming by 6 cycles
if (DCacheStreamPtr < 7) if (DCacheStreamPtr < 7)
@ -2228,27 +2222,28 @@ void ARMv5::CodeRead32_2()
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time; if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
} }
if (PU_Map[FetchAddr[16]>>12] & 0x30) if (PU_Map[addr>>12] & 0x30)
WriteBufferDrain(); WriteBufferDrain();
else else
WriteBufferCheck<3>(); WriteBufferCheck<3>();
QueueFunction(&ARMv5::CodeRead32_3); FetchAddr[16] = addr;
QueueFunction(&ARMv5::CodeRead32_2);
} }
void ARMv5::CodeRead32_3() void ARMv5::CodeRead32_2()
{ {
u32 addr = FetchAddr[16]; u32 addr = FetchAddr[16];
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1); NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
u8 cycles = MemTimings[addr >> 14][1];
if ((addr >> 24) == 0x02) if ((addr >> 24) == 0x02)
{ {
FetchAddr[16] = addr; FetchAddr[16] = addr;
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MRCodeFetch | MR32; MRTrack.Var = MRCodeFetch | MR32;
QueueFunction(DelayedQueue);
} }
else else
{ {
@ -2256,28 +2251,18 @@ void ARMv5::CodeRead32_3()
|| (Store && (NDS.ARM9Regions[addr>>14] == DataRegion))) //check the actual store || (Store && (NDS.ARM9Regions[addr>>14] == DataRegion))) //check the actual store
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
QueueFunction(&ARMv5::CodeRead32_4);
}
}
void ARMv5::CodeRead32_4()
{
u32 addr = FetchAddr[16];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
u8 cycles = MemTimings[addr >> 14][1];
NDS.ARM9Timestamp += cycles; NDS.ARM9Timestamp += cycles;
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
RetVal = BusRead32(addr);
}
Store = false; Store = false;
DataRegion = Mem9_Null; DataRegion = Mem9_Null;
RetVal = BusRead32(addr);
QueueFunction(DelayedQueue); QueueFunction(DelayedQueue);
return;
} }
@ -2361,15 +2346,6 @@ void ARMv5::DRead8_2()
} }
#endif #endif
QueueFunction(&ARMv5::DRead8_3);
}
void ARMv5::DRead8_3()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp; if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles // bus reads can only overlap with icache streaming by 6 cycles
// checkme: does dcache trigger this? // checkme: does dcache trigger this?
@ -2384,10 +2360,10 @@ void ARMv5::DRead8_3()
else else
WriteBufferCheck<1>(); WriteBufferCheck<1>();
QueueFunction(&ARMv5::DRead8_4); QueueFunction(&ARMv5::DRead8_3);
} }
void ARMv5::DRead8_4() void ARMv5::DRead8_3()
{ {
u8 reg = __builtin_ctz(LDRRegs); u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -2403,29 +2379,16 @@ void ARMv5::DRead8_4()
} }
else else
{ {
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
QueueFunction(&ARMv5::DRead8_5);
}
}
void ARMv5::DRead8_5()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
DataCycles = 3<<NDS.ARM9ClockShift;
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead8(addr); *val = BusRead8(addr);
}
} }
void ARMv5::DCacheFin16() void ARMv5::DCacheFin16()
@ -2498,15 +2461,6 @@ void ARMv5::DRead16_2()
} }
#endif #endif
QueueFunction(&ARMv5::DRead16_3);
}
void ARMv5::DRead16_3()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp; if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles // bus reads can only overlap with icache streaming by 6 cycles
// checkme: does cache trigger this? // checkme: does cache trigger this?
@ -2521,10 +2475,10 @@ void ARMv5::DRead16_3()
else else
WriteBufferCheck<1>(); WriteBufferCheck<1>();
QueueFunction(&ARMv5::DRead16_4); QueueFunction(&ARMv5::DRead16_3);
} }
void ARMv5::DRead16_4() void ARMv5::DRead16_3()
{ {
u8 reg = __builtin_ctz(LDRRegs); u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -2540,29 +2494,16 @@ void ARMv5::DRead16_4()
} }
else else
{ {
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
QueueFunction(&ARMv5::DRead16_5);
}
}
void ARMv5::DRead16_5()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
DataCycles = 3<<NDS.ARM9ClockShift;
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead16(addr); *val = BusRead16(addr);
}
} }
void ARMv5::DCacheFin32() void ARMv5::DCacheFin32()
@ -2636,15 +2577,6 @@ void ARMv5::DRead32_2()
} }
#endif #endif
QueueFunction(&ARMv5::DRead32_3);
}
void ARMv5::DRead32_3()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp; if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles // bus reads can only overlap with icache streaming by 6 cycles
// checkme: does cache trigger this? // checkme: does cache trigger this?
@ -2659,10 +2591,10 @@ void ARMv5::DRead32_3()
else else
WriteBufferCheck<1>(); WriteBufferCheck<1>();
QueueFunction(&ARMv5::DRead32_4); QueueFunction(&ARMv5::DRead32_3);
} }
void ARMv5::DRead32_4() void ARMv5::DRead32_3()
{ {
u8 reg = __builtin_ctz(LDRRegs); u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -2675,34 +2607,19 @@ void ARMv5::DRead32_4()
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MR32; MRTrack.Var = MR32;
MRTrack.Progress = reg; MRTrack.Progress = reg;
LDRRegs &= ~1<<reg;
} }
else else
{ {
NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
QueueFunction(&ARMv5::DRead32_5);
}
}
void ARMv5::DRead32_5()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
DataCycles = 3<<NDS.ARM9ClockShift;
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead32(addr); *val = BusRead32(addr);
}
LDRRegs &= ~1<<reg; LDRRegs &= ~1<<reg;
} }
@ -2762,15 +2679,6 @@ void ARMv5::DRead32S_2()
} }
#endif #endif
QueueFunction(&ARMv5::DRead32S_3);
}
void ARMv5::DRead32S_3()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp; if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles // bus reads can only overlap with icache streaming by 6 cycles
// checkme: does cache trigger this? // checkme: does cache trigger this?
@ -2785,10 +2693,10 @@ void ARMv5::DRead32S_3()
else else
WriteBufferCheck<1>(); WriteBufferCheck<1>();
QueueFunction(&ARMv5::DRead32S_4); QueueFunction(&ARMv5::DRead32S_3);
} }
void ARMv5::DRead32S_4() void ARMv5::DRead32S_3()
{ {
u8 reg = __builtin_ctz(LDRRegs); u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -2802,16 +2710,18 @@ void ARMv5::DRead32S_4()
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MR32 | MRSequential; MRTrack.Var = MR32 | MRSequential;
MRTrack.Progress = reg; MRTrack.Progress = reg;
LDRRegs &= ~1<<reg;
} }
else else
{ {
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
DataCycles = MemTimings[addr>>14][2];
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
QueueFunction(&ARMv5::DRead32S_5A); if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead32(addr);
} }
} }
else // ns else // ns
@ -2823,53 +2733,20 @@ void ARMv5::DRead32S_4()
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MR32; MRTrack.Var = MR32;
MRTrack.Progress = reg; MRTrack.Progress = reg;
LDRRegs &= ~1<<reg;
} }
else else
{ {
NDS.ARM9Timestamp += MemTimings[addr>>14][1];
DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift; NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
QueueFunction(&ARMv5::DRead32S_5B);
}
}
}
void ARMv5::DRead32S_5A()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
DataCycles = MemTimings[addr>>14][2];
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead32(addr);
LDRRegs &= ~1<<reg;
}
void ARMv5::DRead32S_5B()
{
u8 reg = __builtin_ctz(LDRRegs);
u32 addr = FetchAddr[reg];
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr>>14][1];
DataCycles = 3<<NDS.ARM9ClockShift;
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
*val = BusRead32(addr); *val = BusRead32(addr);
}
}
LDRRegs &= ~1<<reg; LDRRegs &= ~1<<reg;
} }
@ -2938,6 +2815,16 @@ void ARMv5::DWrite8_2()
if (!(PU_Map[addr>>12] & (0x30))) if (!(PU_Map[addr>>12] & (0x30)))
{ {
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite8_3); QueueFunction(&ARMv5::DWrite8_3);
} }
else else
@ -2950,21 +2837,6 @@ void ARMv5::DWrite8_2()
} }
void ARMv5::DWrite8_3() void ARMv5::DWrite8_3()
{
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite8_4);
}
void ARMv5::DWrite8_4()
{ {
u8 reg = __builtin_ctz(STRRegs); u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -2980,26 +2852,14 @@ void ARMv5::DWrite8_4()
} }
else else
{ {
QueueFunction(&ARMv5::DWrite8_5);
}
}
void ARMv5::DWrite8_5()
{
u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg];
u8 val = STRVal[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr >> 14][0]; NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
DataCycles = 3<<NDS.ARM9ClockShift; DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite8(addr, val); BusWrite8(addr, val);
}
} }
bool ARMv5::DataWrite16(u32 addr, u16 val, u8 reg) bool ARMv5::DataWrite16(u32 addr, u16 val, u8 reg)
@ -3069,6 +2929,16 @@ void ARMv5::DWrite16_2()
if (!(PU_Map[addr>>12] & 0x30)) if (!(PU_Map[addr>>12] & 0x30))
{ {
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite16_3); QueueFunction(&ARMv5::DWrite16_3);
} }
else else
@ -3081,21 +2951,6 @@ void ARMv5::DWrite16_2()
} }
void ARMv5::DWrite16_3() void ARMv5::DWrite16_3()
{
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite16_4);
}
void ARMv5::DWrite16_4()
{ {
u8 reg = __builtin_ctz(STRRegs); u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -3111,26 +2966,14 @@ void ARMv5::DWrite16_4()
} }
else else
{ {
QueueFunction(&ARMv5::DWrite16_5);
}
}
void ARMv5::DWrite16_5()
{
u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg];
u16 val = STRVal[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr >> 14][0]; NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
DataCycles = 3<<NDS.ARM9ClockShift; DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite16(addr, val); BusWrite16(addr, val);
}
} }
bool ARMv5::DataWrite32(u32 addr, u32 val, u8 reg) bool ARMv5::DataWrite32(u32 addr, u32 val, u8 reg)
@ -3205,6 +3048,16 @@ void ARMv5::DWrite32_2()
if (!(PU_Map[addr>>12] & 0x30)) if (!(PU_Map[addr>>12] & 0x30))
{ {
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite32_3); QueueFunction(&ARMv5::DWrite32_3);
} }
else else
@ -3218,21 +3071,6 @@ void ARMv5::DWrite32_2()
} }
void ARMv5::DWrite32_3() void ARMv5::DWrite32_3()
{
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite32_4);
}
void ARMv5::DWrite32_4()
{ {
u8 reg = __builtin_ctz(STRRegs); u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -3245,31 +3083,17 @@ void ARMv5::DWrite32_4()
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MRWrite | MR32; MRTrack.Var = MRWrite | MR32;
MRTrack.Progress = reg; MRTrack.Progress = reg;
STRRegs &= ~1<<reg;
} }
else else
{ {
QueueFunction(&ARMv5::DWrite32_5);
}
}
void ARMv5::DWrite32_5()
{
u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg];
u32 val = STRVal[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr >> 14][1]; NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
DataCycles = 3<<NDS.ARM9ClockShift; DataCycles = 3<<NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite32(addr, val); BusWrite32(addr, val);
}
STRRegs &= ~1<<reg; STRRegs &= ~1<<reg;
} }
@ -3338,6 +3162,15 @@ void ARMv5::DWrite32S_2()
if (!(PU_Map[addr>>12] & 0x30)) // non-bufferable if (!(PU_Map[addr>>12] & 0x30)) // non-bufferable
{ {
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite32S_3); QueueFunction(&ARMv5::DWrite32S_3);
} }
else else
@ -3348,20 +3181,6 @@ void ARMv5::DWrite32S_2()
} }
void ARMv5::DWrite32S_3() void ARMv5::DWrite32S_3()
{
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
// bus reads can only overlap with icache streaming by 6 cycles
// checkme: do buffered writes trigger this?
if (ICacheStreamPtr < 7)
{
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
}
WriteBufferCheck<2>();
QueueFunction(&ARMv5::DWrite32S_4);
}
void ARMv5::DWrite32S_4()
{ {
u8 reg = __builtin_ctz(STRRegs); u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg]; u32 addr = FetchAddr[reg];
@ -3375,12 +3194,15 @@ void ARMv5::DWrite32S_4()
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MRWrite | MR32 | MRSequential; MRTrack.Var = MRWrite | MR32 | MRSequential;
MRTrack.Progress = reg; MRTrack.Progress = reg;
STRRegs &= ~1<<reg;
} }
else else
{ {
QueueFunction(&ARMv5::DWrite32S_5A); NDS.ARM9Timestamp += MemTimings[addr>>14][2];
DataRegion = NDS.ARM9Regions[addr>>14];
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite32(addr, val);
} }
} }
else // ns else // ns
@ -3392,50 +3214,18 @@ void ARMv5::DWrite32S_4()
MRTrack.Type = MainRAMType::Fetch; MRTrack.Type = MainRAMType::Fetch;
MRTrack.Var = MRWrite | MR32; MRTrack.Var = MRWrite | MR32;
MRTrack.Progress = reg; MRTrack.Progress = reg;
STRRegs &= ~1<<reg;
} }
else else
{ {
QueueFunction(&ARMv5::DWrite32S_5B);
}
}
}
void ARMv5::DWrite32S_5A()
{
u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg];
u32 val = STRVal[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
DataRegion = NDS.ARM9Regions[addr>>14];
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite32(addr, val);
STRRegs &= ~1<<reg;
}
void ARMv5::DWrite32S_5B()
{
u8 reg = __builtin_ctz(STRRegs);
u32 addr = FetchAddr[reg];
u32 val = STRVal[reg];
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
NDS.ARM9Timestamp += MemTimings[addr>>14][1]; NDS.ARM9Timestamp += MemTimings[addr>>14][1];
DataCycles = 3 << NDS.ARM9ClockShift; DataCycles = 3 << NDS.ARM9ClockShift;
DataRegion = NDS.ARM9Regions[addr>>14]; DataRegion = NDS.ARM9Regions[addr>>14];
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1))) if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
BusWrite32(addr, val); BusWrite32(addr, val);
}
}
STRRegs &= ~1<<reg; STRRegs &= ~1<<reg;
} }

View File

@ -146,10 +146,7 @@ void DMA::WriteCnt(u32 val)
StartMode = ((Cnt >> 28) & 0x3) | 0x10; StartMode = ((Cnt >> 28) & 0x3) | 0x10;
if ((StartMode & 0x7) == 0) if ((StartMode & 0x7) == 0)
{ Start();
NDS.DMAsQueued[NDS.DMAQueuePtr++] = (CPU*4)+Num;
if (!(NDS.SchedListMask & (1<<Event_DMA))) NDS.ScheduleEvent(Event_DMA, false, 1, 0, 0);
}
else if (StartMode == 0x07) else if (StartMode == 0x07)
NDS.GPU.GPU3D.CheckFIFODMA(); NDS.GPU.GPU3D.CheckFIFODMA();
@ -215,18 +212,6 @@ void DMA::Start()
InProgress = true; InProgress = true;
NDS.StopCPU(CPU, 1<<Num); NDS.StopCPU(CPU, 1<<Num);
if (CPU == 0)
{
u64 ts;
/*if (StartMode == 0x00)
{
ts = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
}
else*/ ts = NDS.SysTimestamp << NDS.ARM9ClockShift;
if (NDS.DMA9Timestamp < ts) NDS.DMA9Timestamp = ts;
}
if (Num == 0) NDS.DMAs[(CPU*4)+1].ResetBurst(); if (Num == 0) NDS.DMAs[(CPU*4)+1].ResetBurst();
if (Num <= 1) NDS.DMAs[(CPU*4)+2].ResetBurst(); if (Num <= 1) NDS.DMAs[(CPU*4)+2].ResetBurst();
if (Num <= 2) NDS.DMAs[(CPU*4)+3].ResetBurst(); if (Num <= 2) NDS.DMAs[(CPU*4)+3].ResetBurst();
@ -602,8 +587,8 @@ u32 DMA::UnitTimings7_32(int burststart)
void DMA::Run9() void DMA::Run9()
{ {
//NDS.DMA9Timestamp = std::max(NDS.DMA9Timestamp, NDS.SysTimestamp << NDS.ARM9ClockShift); NDS.DMA9Timestamp = std::max(NDS.DMA9Timestamp, NDS.ARM9Timestamp);
//NDS.DMA9Timestamp = (NDS.DMA9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1); NDS.DMA9Timestamp = (NDS.DMA9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
if (NDS.DMA9Timestamp-1 >= NDS.ARM9Target) return; if (NDS.DMA9Timestamp-1 >= NDS.ARM9Target) return;

View File

@ -75,7 +75,7 @@ public:
void ResetBurst() void ResetBurst()
{ {
if (Running > 0) Running = 3; if (Running > 0) Running = (CPU ? 2 : 3);
} }
u32 SrcAddr {}; u32 SrcAddr {};

View File

@ -124,7 +124,6 @@ NDS::NDS(NDSArgs&& args, int type, void* userdata) noexcept :
{ {
RegisterEventFuncs(Event_Div, this, {MakeEventThunk(NDS, DivDone)}); RegisterEventFuncs(Event_Div, this, {MakeEventThunk(NDS, DivDone)});
RegisterEventFuncs(Event_Sqrt, this, {MakeEventThunk(NDS, SqrtDone)}); RegisterEventFuncs(Event_Sqrt, this, {MakeEventThunk(NDS, SqrtDone)});
RegisterEventFuncs(Event_DMA, this, {MakeEventThunk(NDS, QueueDMAs)});
MainRAM = JIT.Memory.GetMainRAM(); MainRAM = JIT.Memory.GetMainRAM();
SharedWRAM = JIT.Memory.GetSharedWRAM(); SharedWRAM = JIT.Memory.GetSharedWRAM();
@ -135,7 +134,6 @@ NDS::~NDS() noexcept
{ {
UnregisterEventFuncs(Event_Div); UnregisterEventFuncs(Event_Div);
UnregisterEventFuncs(Event_Sqrt); UnregisterEventFuncs(Event_Sqrt);
UnregisterEventFuncs(Event_DMA);
// The destructor for each component is automatically called by the compiler // The destructor for each component is automatically called by the compiler
} }
@ -550,9 +548,6 @@ void NDS::Reset()
KeyCnt[1] = 0; KeyCnt[1] = 0;
RCnt = 0; RCnt = 0;
memset(DMAsQueued, 0, sizeof(DMAsQueued));
DMAQueuePtr = 0;
GPU.Reset(); GPU.Reset();
NDSCartSlot.Reset(); NDSCartSlot.Reset();
GBACartSlot.Reset(); GBACartSlot.Reset();
@ -845,21 +840,6 @@ void NDS::RunSystem(u64 timestamp)
} }
} }
void NDS::RunEventManual(u32 id)
{
if (SchedListMask & (1<<id))
{
u64 curts = CurCPU ? ARM7Timestamp : (std::max(ARM9Timestamp, DMA9Timestamp) >> ARM9ClockShift);
SchedEvent& evt = SchedList[id];
if (evt.Timestamp <= curts)
{
evt.Funcs[evt.FuncID](evt.That, evt.Param);
SchedListMask &= ~(1<<id);
}
}
}
u64 NDS::NextTargetSleep() u64 NDS::NextTargetSleep()
{ {
u64 minEvent = UINT64_MAX; u64 minEvent = UINT64_MAX;
@ -1665,19 +1645,13 @@ bool NDS::MainRAMHandle()
{ {
if (A9ContentionTS < ARM7Timestamp) if (A9ContentionTS < ARM7Timestamp)
{ {
if (ARM9.MRTrack.Type == MainRAMType::Null) return 0; if (ARM9.MRTrack.Type == MainRAMType::Null || (CPUStop & CPUStop_GXStall)) return 0;
else if (CPUStop & CPUStop_GXStall) MainRAMHandleARM9();
{
// gx stalls can occur during this, and if not handled properly will cause issues
s32 cycles = GPU.GPU3D.CyclesToRunFor();
A9ContentionTS = std::min(ARM9Target, A9ContentionTS+cycles);
}
else MainRAMHandleARM9();
} }
else else
{ {
if (ARM7.MRTrack.Type == MainRAMType::Null) return 1; if (ARM7.MRTrack.Type == MainRAMType::Null) return 1;
else MainRAMHandleARM7(); MainRAMHandleARM7();
} }
} }
} }
@ -1687,19 +1661,13 @@ bool NDS::MainRAMHandle()
{ {
if (A9ContentionTS <= ARM7Timestamp) if (A9ContentionTS <= ARM7Timestamp)
{ {
if (ARM9.MRTrack.Type == MainRAMType::Null) return 0; if (ARM9.MRTrack.Type == MainRAMType::Null || (CPUStop & CPUStop_GXStall)) return 0;
else if (CPUStop & CPUStop_GXStall) MainRAMHandleARM9();
{
// gx stalls can occur during this, and if not handled properly will cause issues
s32 cycles = GPU.GPU3D.CyclesToRunFor();
A9ContentionTS = std::min(ARM9Target, A9ContentionTS+cycles);
}
else MainRAMHandleARM9();
} }
else else
{ {
if (ARM7.MRTrack.Type == MainRAMType::Null) return 1; if (ARM7.MRTrack.Type == MainRAMType::Null) return 1;
else MainRAMHandleARM7(); MainRAMHandleARM7();
} }
} }
} }
@ -1772,11 +1740,8 @@ u32 NDS::RunFrame()
u64 target = NextTarget(); u64 target = NextTarget();
ARM9Target = target << ARM9ClockShift; ARM9Target = target << ARM9ClockShift;
ARM7Target = target; //ARM7Target = target;
while (((std::max(std::max(ARM9Timestamp, DMA9Timestamp), A9ContentionTS << ARM9ClockShift) < ARM9Target) && (ARM9.MRTrack.Type == MainRAMType::Null))
|| (ARM7Timestamp < ARM7Target) && (ARM7.MRTrack.Type == MainRAMType::Null))
{
while (std::max(std::max(ARM9Timestamp, DMA9Timestamp), A9ContentionTS << ARM9ClockShift) < ARM9Target) while (std::max(std::max(ARM9Timestamp, DMA9Timestamp), A9ContentionTS << ARM9ClockShift) < ARM9Target)
{ {
CurCPU = 0; CurCPU = 0;
@ -1810,17 +1775,22 @@ u32 NDS::RunFrame()
} }
} }
//printf("MAIN LOOP: 9 %lli %lli %08X %08llX %i 7 %lli %lli %08X %08llX %i\n", ARM9Timestamp, ARM9Target, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7Target, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type); //printf("MAIN LOOP: 9 %lli %08X %08llX %i 7 %lli %08X %08llX %i %i %08X\n", ARM9Timestamp>>ARM9ClockShift, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type, IME[1], IE[1]);
NDSCartSlot.ROMPrepareData();
RunTimers(0); RunTimers(0);
GPU.GPU3D.Run(); GPU.GPU3D.Run();
if (MainRAMHandle()) break; //if (MainRAMHandle()) break;
} MainRAMHandle();
while (ARM7Timestamp < ARM7Target) target = std::max(std::max(ARM9Timestamp, DMA9Timestamp) >> ARM9ClockShift, A9ContentionTS);
if (target == ARM7Timestamp) target++;
while (ARM7Timestamp < target)
{ {
//printf("A7 LOOP: 9 %lli %lli %08X %08llX %i 7 %lli %lli %08X %08llX %i\n", ARM9Timestamp, ARM9Target, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7Target, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type); ARM7Target = target;
//printf("A7 LOOP: %lli %lli\n", ARM9Timestamp>>ARM9ClockShift, ARM7Timestamp);
CurCPU = 1; CurCPU = 1;
RunTimers(1); RunTimers(1);
@ -1846,12 +1816,13 @@ u32 NDS::RunFrame()
} }
RunTimers(1); RunTimers(1);
NDSCartSlot.ROMPrepareData();
if (!MainRAMHandle()) break; if (!MainRAMHandle()) break;
} }
} }
RunSystem(ARM7Target); RunSystem(target);
if (CPUStop & CPUStop_Sleep) if (CPUStop & CPUStop_Sleep)
{ {
@ -1873,6 +1844,7 @@ u32 NDS::RunFrame()
SPU.TransferOutput(); SPU.TransferOutput();
break; break;
} }
//printf("MAIN LOOP: 9 %lli %08X %08llX %i 7 %lli %08X %08llX %i %i %08X\n", ARM9Timestamp>>ARM9ClockShift, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type, IME[1], IE[1]);
// In the context of TASes, frame count is traditionally the primary measure of emulated time, // In the context of TASes, frame count is traditionally the primary measure of emulated time,
// so it needs to be tracked even if NDS is powered off. // so it needs to be tracked even if NDS is powered off.
@ -1906,11 +1878,13 @@ u32 NDS::RunFrame()
void NDS::Reschedule(u64 target) void NDS::Reschedule(u64 target)
{ {
if (target < ARM7Target) if (CurCPU == 0)
{ {
ARM7Target = target; if (target < (ARM9Target >> ARM9ClockShift))
ARM9Target = (target << ARM9ClockShift); ARM9Target = (target << ARM9ClockShift);
} }
else if (target < ARM7Target)
ARM7Target = target;
} }
void NDS::RegisterEventFuncs(u32 id, void* that, const std::initializer_list<EventFunc>& funcs) void NDS::RegisterEventFuncs(u32 id, void* that, const std::initializer_list<EventFunc>& funcs)
@ -2555,15 +2529,6 @@ void NDS::StopDMAs(u32 cpu, u32 mode)
DMAs[cpu+3].StopIfNeeded(mode); DMAs[cpu+3].StopIfNeeded(mode);
} }
void NDS::QueueDMAs(u32 param)
{
DMAs[DMAsQueued[0]].Start();
for(int i = 0; i < 7; i++) DMAsQueued[i] = DMAsQueued[i+1];
DMAQueuePtr--;
if (DMAQueuePtr != 0) ScheduleEvent(Event_DMA, false, 1, 0, 0);
}
void NDS::DivDone(u32 param) void NDS::DivDone(u32 param)

View File

@ -64,7 +64,6 @@ enum
Event_SPITransfer, Event_SPITransfer,
Event_Div, Event_Div,
Event_Sqrt, Event_Sqrt,
Event_DMA,
// DSi // DSi
Event_DSi_SDMMCTransfer, Event_DSi_SDMMCTransfer,
@ -245,7 +244,6 @@ public: // TODO: Encapsulate the rest of these members
int ConsoleType; int ConsoleType;
int CurCPU; int CurCPU;
u32 SchedListMask;
SchedEvent SchedList[Event_MAX] {}; SchedEvent SchedList[Event_MAX] {};
u8 ARM9MemTimings[0x40000][8]; u8 ARM9MemTimings[0x40000][8];
u32 ARM9Regions[0x40000]; u32 ARM9Regions[0x40000];
@ -261,7 +259,6 @@ public: // TODO: Encapsulate the rest of these members
u64 ARM7Timestamp, ARM7Target; u64 ARM7Timestamp, ARM7Target;
u64 MainRAMTimestamp, MainRAMBurstStart; u64 MainRAMTimestamp, MainRAMBurstStart;
u64 A9ContentionTS; bool ConTSLock; u64 A9ContentionTS; bool ConTSLock;
u64 SysTimestamp;
u32 ARM9ClockShift; u32 ARM9ClockShift;
u32 IME[2]; u32 IME[2];
@ -280,8 +277,6 @@ public: // TODO: Encapsulate the rest of these members
alignas(u32) u8 ROMSeed1[2*8]; alignas(u32) u8 ROMSeed1[2*8];
u32 DMAReadHold[2]; u32 DMAReadHold[2];
u8 DMAsQueued[8];
u8 DMAQueuePtr;
bool MainRAMBork; // if a main ram read burst starts in the last 6 bytes of a 32 byte block, and then crosses the 32 byte boundary, the burst forcibly restarts bool MainRAMBork; // if a main ram read burst starts in the last 6 bytes of a 32 byte block, and then crosses the 32 byte boundary, the burst forcibly restarts
bool MainRAMLastAccess; // 0 == ARM9 | 1 == ARM7 bool MainRAMLastAccess; // 0 == ARM9 | 1 == ARM7
bool DMALastWasMainRAM; bool DMALastWasMainRAM;
@ -432,7 +427,6 @@ public: // TODO: Encapsulate the rest of these members
void UnregisterEventFuncs(u32 id); void UnregisterEventFuncs(u32 id);
void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param); void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param);
void CancelEvent(u32 id); void CancelEvent(u32 id);
void RunEventManual(u32 id);
void debug(u32 p); void debug(u32 p);
@ -512,6 +506,8 @@ public: // TODO: Encapsulate the rest of these members
private: private:
void InitTimings(); void InitTimings();
u32 SchedListMask;
u64 SysTimestamp;
u8 WRAMCnt; u8 WRAMCnt;
u8 PostFlag9; u8 PostFlag9;
u8 PostFlag7; u8 PostFlag7;
@ -546,7 +542,6 @@ private:
void HandleTimerOverflow(u32 tid); void HandleTimerOverflow(u32 tid);
u16 TimerGetCounter(u32 timer); u16 TimerGetCounter(u32 timer);
void TimerStart(u32 id, u16 cnt); void TimerStart(u32 id, u16 cnt);
void QueueDMAs(u32 param);
void StartDiv(); void StartDiv();
void DivDone(u32 param); void DivDone(u32 param);
void SqrtDone(u32 param); void SqrtDone(u32 param);

View File

@ -37,8 +37,7 @@ namespace NDSCart
enum enum
{ {
ROMTransfer_PrepareData = 0, ROMTransfer_End = 0
ROMTransfer_End
}; };
// SRAM TODO: emulate write delays??? // SRAM TODO: emulate write delays???
@ -1443,7 +1442,6 @@ NDSCartSlot::NDSCartSlot(melonDS::NDS& nds, std::unique_ptr<CartCommon>&& rom) n
{ {
NDS.RegisterEventFuncs(Event_ROMTransfer, this, NDS.RegisterEventFuncs(Event_ROMTransfer, this,
{ {
MakeEventThunk(NDSCartSlot, ROMPrepareData),
MakeEventThunk(NDSCartSlot, ROMEndTransfer) MakeEventThunk(NDSCartSlot, ROMEndTransfer)
}); });
NDS.RegisterEventFuncs(Event_ROMSPITransfer, this, {MakeEventThunk(NDSCartSlot, SPITransferDone)}); NDS.RegisterEventFuncs(Event_ROMSPITransfer, this, {MakeEventThunk(NDSCartSlot, SPITransferDone)});
@ -1799,7 +1797,8 @@ void NDSCartSlot::ResetCart() noexcept
TransferDir = 0; TransferDir = 0;
memset(TransferCmd.data(), 0, sizeof(TransferCmd)); memset(TransferCmd.data(), 0, sizeof(TransferCmd));
TransferCmd[0] = 0xFF; TransferCmd[0] = 0xFF;
ROMTransferTime = -1; ROMTransferTime[0] = -1;
ROMTransferTime[1] = -1;
if (Cart) Cart->Reset(); if (Cart) Cart->Reset();
} }
@ -1816,8 +1815,14 @@ void NDSCartSlot::ROMEndTransfer(u32 param) noexcept
Cart->ROMCommandFinish(TransferCmd.data(), TransferData.data(), TransferLen); Cart->ROMCommandFinish(TransferCmd.data(), TransferData.data(), TransferLen);
} }
void NDSCartSlot::ROMPrepareData(u32 param) noexcept void NDSCartSlot::ROMPrepareData() noexcept
{ {
u64 curts;
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
if (curts < ROMTransferTime[0]) return;
if (TransferDir == 0) if (TransferDir == 0)
{ {
if (TransferPos >= TransferLen) if (TransferPos >= TransferLen)
@ -1828,6 +1833,8 @@ void NDSCartSlot::ROMPrepareData(u32 param) noexcept
TransferPos += 4; TransferPos += 4;
} }
ROMTransferTime[0] = -1;
ROMCnt |= (1<<23); ROMCnt |= (1<<23);
if (NDS.ExMemCnt[0] & (1<<11)) if (NDS.ExMemCnt[0] & (1<<11))
@ -1838,7 +1845,7 @@ void NDSCartSlot::ROMPrepareData(u32 param) noexcept
u32 NDSCartSlot::GetROMCnt() noexcept u32 NDSCartSlot::GetROMCnt() noexcept
{ {
NDS.RunEventManual(Event_ROMTransfer); ROMPrepareData();
return ROMCnt; return ROMCnt;
} }
@ -1929,13 +1936,16 @@ void NDSCartSlot::WriteROMCnt(u32 val) noexcept
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*cmddelay, ROMTransfer_End, 0); NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*cmddelay, ROMTransfer_End, 0);
else else
{ {
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMTransfer_PrepareData, 0);
u64 curts; u64 curts;
if (NDS.ExMemCnt[0] & (1<<11)) curts = NDS.ARM7Timestamp; if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift; else curts = ((std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift);
ROMTransferTime = (xfercycle*(cmddelay+8)) + curts; ROMTransferTime[0] = (xfercycle*(cmddelay+4)) + curts;
if ((TransferPos + 4) < TransferLen)
ROMTransferTime[1] = (xfercycle*(cmddelay+8)) + curts;
else
ROMTransferTime[1] = -1;
} }
} }
@ -1954,12 +1964,16 @@ void NDSCartSlot::AdvanceROMTransfer() noexcept
} }
u64 curts; u64 curts;
if (NDS.ExMemCnt[0] & (1<<11)) curts = NDS.ARM7Timestamp; if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift; else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
NDS.ScheduleEvent(Event_ROMTransfer, false, ROMTransferTime-curts, ROMTransfer_PrepareData, 0); ROMTransferTime[0] = ROMTransferTime[1];
if ((TransferPos + 4) < TransferLen)
ROMTransferTime[1] = (xfercycle*delay) + std::max(curts, ROMTransferTime[0]);
else
ROMTransferTime[1] = -1;
ROMTransferTime = (xfercycle*delay) + std::max(curts, ROMTransferTime);
} }
else else
ROMEndTransfer(0); ROMEndTransfer(0);
@ -1969,7 +1983,11 @@ u32 NDSCartSlot::ReadROMData() noexcept
{ {
if (ROMCnt & (1<<30)) return 0; if (ROMCnt & (1<<30)) return 0;
NDS.RunEventManual(Event_ROMTransfer); u64 curts;
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
ROMPrepareData();
if (ROMCnt & (1<<23)) if (ROMCnt & (1<<23))
{ {
@ -1983,7 +2001,11 @@ void NDSCartSlot::WriteROMData(u32 val) noexcept
{ {
if (!(ROMCnt & (1<<30))) return; if (!(ROMCnt & (1<<30))) return;
NDS.RunEventManual(Event_ROMTransfer); u64 curts;
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
ROMPrepareData();
ROMData = val; ROMData = val;

View File

@ -410,6 +410,7 @@ public:
void WriteROMCnt(u32 val) noexcept; void WriteROMCnt(u32 val) noexcept;
[[nodiscard]] u8 ReadSPIData() const noexcept; [[nodiscard]] u8 ReadSPIData() const noexcept;
void WriteSPIData(u8 val) noexcept; void WriteSPIData(u8 val) noexcept;
void ROMPrepareData() noexcept;
[[nodiscard]] u8 GetROMCommand(u8 index) const noexcept { return ROMCommand[index]; } [[nodiscard]] u8 GetROMCommand(u8 index) const noexcept { return ROMCommand[index]; }
void SetROMCommand(u8 index, u8 val) noexcept { ROMCommand[index] = val; } void SetROMCommand(u8 index, u8 val) noexcept { ROMCommand[index] = val; }
@ -443,7 +444,8 @@ private:
u64 Key2_X = 0; u64 Key2_X = 0;
u64 Key2_Y = 0; u64 Key2_Y = 0;
u64 ROMTransferTime;
u64 ROMTransferTime[2];
void Key1_Encrypt(u32* data) const noexcept; void Key1_Encrypt(u32* data) const noexcept;
void Key1_Decrypt(u32* data) const noexcept; void Key1_Decrypt(u32* data) const noexcept;
@ -452,7 +454,6 @@ private:
void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) noexcept; void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) noexcept;
void Key2_Encrypt(const u8* data, u32 len) noexcept; void Key2_Encrypt(const u8* data, u32 len) noexcept;
void ROMEndTransfer(u32 param) noexcept; void ROMEndTransfer(u32 param) noexcept;
void ROMPrepareData(u32 param) noexcept;
void AdvanceROMTransfer() noexcept; void AdvanceROMTransfer() noexcept;
void SPITransferDone(u32 param) noexcept; void SPITransferDone(u32 param) noexcept;
}; };