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(); 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 // handle data aborts
if (dabort) [[unlikely]] if (dabort) [[unlikely]]
{ {
@ -735,6 +741,12 @@ void A_STM(ARM* cpu)
cpu->AddCycles_CD(); 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 // handle data aborts
if (dabort) [[unlikely]] if (dabort) [[unlikely]]
{ {
@ -909,6 +921,12 @@ void T_PUSH(ARM* cpu)
cpu->AddCycles_CD(); 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]] if (dabort) [[unlikely]]
{ {
((ARMv5*)cpu)->DataAbort(); ((ARMv5*)cpu)->DataAbort();
@ -952,31 +970,45 @@ void T_POP(ARM* cpu)
dabort |= !(first ? cpu->DataRead32 (base, &pc) dabort |= !(first ? cpu->DataRead32 (base, &pc)
: cpu->DataRead32S(base, &pc)); : cpu->DataRead32S(base, &pc));
if (dabort) [[unlikely]] goto dataabort; if (!dabort) [[likely]]
{
cpu->AddCycles_CDI(); 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; if (cpu->Num==1 || (((ARMv5*)cpu)->CP15Control & (1<<15))) pc |= 0x1;
cpu->JumpTo(pc); cpu->JumpTo(pc);
base += 4; base += 4;
} }
}
else else
{ {
cpu->AddCycles_CDI(); 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 (cpu->Num == 0)
{
if (dabort) [[unlikely]]
{
((ARMv5*)cpu)->DataAbort();
return;
}
else
{ {
u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF); u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF);
((ARMv5*)cpu)->ILCurrReg = lastreg; ((ARMv5*)cpu)->ILCurrReg = lastreg;
((ARMv5*)cpu)->ILCurrTime = ((ARMv5*)cpu)->TimestampActual; ((ARMv5*)cpu)->ILCurrTime = ((ARMv5*)cpu)->TimestampActual;
} }
} }
if (dabort) [[unlikely]]
{
dataabort:
cpu->AddCycles_CDI();
((ARMv5*)cpu)->DataAbort();
return;
} }
cpu->R[13] = base; cpu->R[13] = base;
@ -1015,6 +1047,12 @@ void T_STMIA(ARM* cpu)
cpu->AddCycles_CD(); 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]] if (dabort) [[unlikely]]
{ {
((ARMv5*)cpu)->DataAbort(); ((ARMv5*)cpu)->DataAbort();
@ -1054,6 +1092,12 @@ void T_LDMIA(ARM* cpu)
cpu->AddCycles_CDI(); 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]] if (dabort) [[unlikely]]
{ {
((ARMv5*)cpu)->DataAbort(); ((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][1] = ((bustimings[0] - 1) << NDS.ARM9ClockShift) + 1;
MemTimings[i][2] = ((bustimings[2] - 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 ((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; MainRAMTimestamp = NDS.ARM9Timestamp + DataCycles;
DataRegion = Mem9_MainRAM; DataRegion = Mem9_MainRAM;
} }