add support for 1 reg ldm/stm a9 timings and fix a bug

This commit is contained in:
Jaklyy 2024-10-18 17:56:56 -04:00
parent 8ff0946b8a
commit 9ed4c66592
2 changed files with 63 additions and 19 deletions

View File

@ -617,6 +617,12 @@ void A_LDM(ARM* cpu)
cpu->AddCycles_CDI();
if (__builtin_popcount(cpu->CurInstr & 0xFFFF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
// handle data aborts
if (dabort) [[unlikely]]
{
@ -735,6 +741,12 @@ void A_STM(ARM* cpu)
cpu->AddCycles_CD();
if (__builtin_popcount(cpu->CurInstr & 0xFFFF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
// handle data aborts
if (dabort) [[unlikely]]
{
@ -909,6 +921,12 @@ void T_PUSH(ARM* cpu)
cpu->AddCycles_CD();
if (__builtin_popcount(cpu->CurInstr & 0x1FF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
if (dabort) [[unlikely]]
{
((ARMv5*)cpu)->DataAbort();
@ -952,31 +970,45 @@ void T_POP(ARM* cpu)
dabort |= !(first ? cpu->DataRead32 (base, &pc)
: cpu->DataRead32S(base, &pc));
if (dabort) [[unlikely]] goto dataabort;
if (!dabort) [[likely]]
{
cpu->AddCycles_CDI();
if (__builtin_popcount(cpu->CurInstr & 0x1FF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
if (cpu->Num==1 || (((ARMv5*)cpu)->CP15Control & (1<<15))) pc |= 0x1;
cpu->JumpTo(pc);
base += 4;
}
}
else
{
cpu->AddCycles_CDI();
if (__builtin_popcount(cpu->CurInstr & 0x1FF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
if (cpu->Num == 0)
{
if (dabort) [[unlikely]]
{
((ARMv5*)cpu)->DataAbort();
return;
}
else
{
u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF);
((ARMv5*)cpu)->ILCurrReg = lastreg;
((ARMv5*)cpu)->ILCurrTime = ((ARMv5*)cpu)->TimestampActual;
}
}
if (dabort) [[unlikely]]
{
dataabort:
cpu->AddCycles_CDI();
((ARMv5*)cpu)->DataAbort();
return;
}
cpu->R[13] = base;
@ -1015,6 +1047,12 @@ void T_STMIA(ARM* cpu)
cpu->AddCycles_CD();
if (__builtin_popcount(cpu->CurInstr & 0xFF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
if (dabort) [[unlikely]]
{
((ARMv5*)cpu)->DataAbort();
@ -1054,6 +1092,12 @@ void T_LDMIA(ARM* cpu)
cpu->AddCycles_CDI();
if (__builtin_popcount(cpu->CurInstr & 0xFF) == 1) [[unlikely]] // single reg
{
if (cpu->Num == 0) cpu->NDS.ARM9Timestamp = ((ARMv5*)cpu)->TimestampActual; // on arm9 single reg ldm/stm cannot overlap memory and fetch stages
else; // CHECKME: ARM7 timing behavior?
}
if (dabort) [[unlikely]]
{
((ARMv5*)cpu)->DataAbort();

View File

@ -321,7 +321,7 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
{
MemTimings[i][1] = ((bustimings[0] - 1) << NDS.ARM9ClockShift) + 1;
MemTimings[i][2] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1;
MemTimings[i][3] = bustimings[3] << NDS.ARM9ClockShift; // inaccurate but ehgh
MemTimings[i][3] = ((bustimings[3] - 1) << NDS.ARM9ClockShift) + 1;; // inaccurate but ehgh
}
}
}
@ -1367,7 +1367,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val)
if ((addr >> 24) == 0x02)
{
if ((DataRegion != Mem9_MainRAM) && ((NDS.ARM9Timestamp + DataCycles) < MainRAMTimestamp)) NDS.ARM9Timestamp = MainRAMTimestamp - DataCycles;
if ((DataRegion != Mem9_MainRAM) && ((NDS.ARM9Timestamp + DataCycles) < MainRAMTimestamp)) DataCycles += MainRAMTimestamp - NDS.ARM9Timestamp;
MainRAMTimestamp = NDS.ARM9Timestamp + DataCycles;
DataRegion = Mem9_MainRAM;
}