From 9ed4c665920bc1ed5ea1ccf8452020d292f62ee2 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Fri, 18 Oct 2024 17:56:56 -0400 Subject: [PATCH] add support for 1 reg ldm/stm a9 timings and fix a bug --- src/ARMInterpreter_LoadStore.cpp | 78 +++++++++++++++++++++++++------- src/CP15.cpp | 4 +- 2 files changed, 63 insertions(+), 19 deletions(-) diff --git a/src/ARMInterpreter_LoadStore.cpp b/src/ARMInterpreter_LoadStore.cpp index 93ea54dc..b965c078 100644 --- a/src/ARMInterpreter_LoadStore.cpp +++ b/src/ARMInterpreter_LoadStore.cpp @@ -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,33 +970,47 @@ 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(); - cpu->AddCycles_CDI(); - if (cpu->Num==1 || (((ARMv5*)cpu)->CP15Control & (1<<15))) pc |= 0x1; - cpu->JumpTo(pc); - base += 4; + 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) { - u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF); - ((ARMv5*)cpu)->ILCurrReg = lastreg; - ((ARMv5*)cpu)->ILCurrTime = ((ARMv5*)cpu)->TimestampActual; + 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,12 +1092,18 @@ 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(); return; } - + if (cpu->Num == 0) { u8 lastreg = 31 - __builtin_clz(cpu->CurInstr & 0xFF); diff --git a/src/CP15.cpp b/src/CP15.cpp index 44b7e88a..6c9c7951 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -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; }