From 299713e412f401977a62ddebe77a03cb6b3689cd Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Thu, 5 Sep 2024 09:13:46 -0400 Subject: [PATCH] basic arm9 set up --- src/ARM.cpp | 37 +++++++++++---- src/ARM.h | 56 ++++++++++++----------- src/CP15.cpp | 127 ++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 177 insertions(+), 43 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index e3c07397..105607f5 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -151,6 +151,7 @@ void ARM::Reset() { Cycles = 0; Halted = 0; + DataCycles = 0; IRQ = 0; @@ -199,6 +200,13 @@ void ARM::Reset() void ARMv5::Reset() { PU_Map = PU_PrivMap; + + TimestampActual = 0; + InterlockMem = 16; + InterlockWBCur = 16; + InterlockWBPrev = 16; + Store = false; + InterlockMask = 0; ARM::Reset(); } @@ -310,14 +318,12 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) u32 oldregion = R[15] >> 24; u32 newregion = addr >> 24; - RegionCodeCycles = MemTimings[addr >> 12][0]; - if (addr & 0x1) { addr &= ~0x1; R[15] = addr+2; - if (newregion != oldregion) SetupCodeMem(addr); + //if (newregion != oldregion) SetupCodeMem(addr); // two-opcodes-at-once fetch // doesn't matter if we put garbage in the MSbs there @@ -342,7 +348,7 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr) addr &= ~0x3; R[15] = addr+4; - if (newregion != oldregion) SetupCodeMem(addr); + //if (newregion != oldregion) SetupCodeMem(addr); NextInstr[0] = CodeRead32(addr, true); Cycles += CodeCycles; @@ -744,8 +750,8 @@ void ARMv5::Execute() }*/ } - NDS.ARM9Timestamp += Cycles; - Cycles = 0; + //NDS.ARM9Timestamp += Cycles; + //Cycles = 0; } if (Halted == 2) @@ -816,7 +822,7 @@ void ARMv4::Execute() { if ((Halted == 1 || IdleLoop) && NDS.ARM7Timestamp < NDS.ARM7Target) { - //Cycles = 0; + Cycles = 0; NDS.ARM7Timestamp = NDS.ARM7Target; } IdleLoop = 0; @@ -882,9 +888,6 @@ void ARMv4::Execute() TriggerIRQ(); }*/ } - - //NDS.ARM7Timestamp += Cycles; - //Cycles = 0; } if (Halted == 2) @@ -1153,6 +1156,20 @@ u32 ARMv5::ReadMem(u32 addr, int size) } #endif + +void ARMv5::AddCycles_CI(s32 numI) +{ + NDS.ARM9Timestamp += numI; +} + +void ARMv5::AddCycles_MW() +{ + u64 TimestampActual = DataCycles + NDS.ARM9Timestamp; + s32 cycles = DataCycles - (3< 0) NDS.ARM9Timestamp += cycles; +} + u16 ARMv4::CodeRead16(u32 addr) { if ((addr >> 24) == 0x02) diff --git a/src/ARM.h b/src/ARM.h index f878d94b..31ff56cc 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -265,44 +265,41 @@ public: bool DataWrite16(u32 addr, u16 val) override; bool DataWrite32(u32 addr, u32 val) override; bool DataWrite32S(u32 addr, u32 val, bool dataabort = false) override; + + template + void ExecuteStage(u8 rn, u8 rm) + { + static_assert((nregs < 2), "too many regs"); + + if constexpr (nregs == 1) + { + InterlockMask = 1 << rn; + } + if constexpr (nregs == 2) + { + InterlockMask = 1 << rn | 1 << rm; + } + + AddCycles_C(); + } + void AddCycles_C() override { - // code only. always nonseq 32-bit for ARM9. - s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; - Cycles += numC; } - void AddCycles_CI(s32 numI) override - { - // code+internal - s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; - Cycles += numC + numI; - } + void AddCycles_CI(s32 numI) override; + + void AddCycles_MW(); void AddCycles_CDI() override { - // LDR/LDM cycles. ARM9 seems to skip the internal cycle there. - // TODO: ITCM data fetches shouldn't be parallelized, they say - s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; - s32 numD = DataCycles; - - //if (DataRegion != CodeRegion) - Cycles += std::max(numC + numD - 6, std::max(numC, numD)); - //else - // Cycles += numC + numD; + AddCycles_MW(); } void AddCycles_CD() override { - // TODO: ITCM data fetches shouldn't be parallelized, they say - s32 numC = (R[15] & 0x2) ? 0 : CodeCycles; - s32 numD = DataCycles; - - //if (DataRegion != CodeRegion) - Cycles += std::max(numC + numD - 6, std::max(numC, numD)); - //else - // Cycles += numC + numD; + AddCycles_MW(); } void GetCodeMemRegion(u32 addr, MemRegion* region); @@ -367,6 +364,13 @@ public: u8* CurICacheLine; bool (*GetMemRegion)(u32 addr, bool write, MemRegion* region); + + u64 TimestampActual; + u8 InterlockMem; + u8 InterlockWBCur; + u8 InterlockWBPrev; + bool Store; + u16 InterlockMask; #ifdef GDBSTUB_ENABLED u32 ReadMem(u32 addr, int size) override; diff --git a/src/CP15.cpp b/src/CP15.cpp index 6fcaff93..eb84d3ee 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -299,13 +299,16 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend) u8 pu = PU_Map[i]; u8* bustimings = NDS.ARM9MemTimings[i >> 2]; + // checkme: should these be (bus timings shifted) - 1 or ((bustimings - 1) shifted) + 1 + // should the last cycle be halved...? + if (pu & 0x40) { MemTimings[i][0] = 0xFF;//kCodeCacheTiming; } else { - MemTimings[i][0] = bustimings[2] << NDS.ARM9ClockShift; + MemTimings[i][0] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1; } if (pu & 0x10) @@ -316,9 +319,9 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend) } else { - MemTimings[i][1] = bustimings[0] << NDS.ARM9ClockShift; - MemTimings[i][2] = bustimings[2] << NDS.ARM9ClockShift; - MemTimings[i][3] = bustimings[3] << NDS.ARM9ClockShift; + MemTimings[i][1] = ((bustimings[0] - 1) << NDS.ARM9ClockShift) + 1; + MemTimings[i][2] = ((bustimings[2] - 1) << NDS.ARM9ClockShift) + 1; + MemTimings[i][3] = ((bustimings[3] - 1) << NDS.ARM9ClockShift) + 1; } } } @@ -784,10 +787,11 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) if (addr < ITCMSize) { CodeCycles = 1; + if ((DataRegion == Mem9_ITCM) && (TimestampActual >= NDS.ARM9Timestamp)) NDS.ARM9Timestamp = TimestampActual + 1; return *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; } - CodeCycles = RegionCodeCycles; + CodeCycles = MemTimings[addr >> 12][0]; if (CodeCycles == 0xFF) // cached memory. hax { if (branch || !(addr & 0x1F)) @@ -798,7 +802,21 @@ u32 ARMv5::CodeRead32(u32 addr, bool branch) //return *(u32*)&CurICacheLine[addr & 0x1C]; } - if (CodeMem.Mem) return *(u32*)&CodeMem.Mem[addr & CodeMem.Mask]; + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + + if (DataRegion == Mem9_MainRAM) NDS.ARM9Timestamp += CodeCycles; + } + + if (CodeRegion == DataRegion && Store) NDS.ARM9Timestamp += (1<>12] & 0x01)) [[unlikely]] { DataAbort(); @@ -815,15 +834,26 @@ bool ARMv5::DataRead8(u32 addr, u32* val) if (addr < ITCMSize) { DataCycles = 1; + DataRegion = Mem9_ITCM; *val = *(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)]; return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; + DataRegion = Mem9_DTCM; *val = *(u8*)&DTCM[addr & (DTCMPhysicalSize - 1)]; return true; } + + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; *val = BusRead8(addr); DataCycles = MemTimings[addr >> 12][1]; @@ -832,6 +862,7 @@ bool ARMv5::DataRead8(u32 addr, u32* val) bool ARMv5::DataRead16(u32 addr, u32* val) { + Store = false; if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]] { DataAbort(); @@ -843,15 +874,26 @@ bool ARMv5::DataRead16(u32 addr, u32* val) if (addr < ITCMSize) { DataCycles = 1; + DataRegion = Mem9_ITCM; *val = *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)]; return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; + DataRegion = Mem9_DTCM; *val = *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)]; return true; } + + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; *val = BusRead16(addr); DataCycles = MemTimings[addr >> 12][1]; @@ -860,6 +902,7 @@ bool ARMv5::DataRead16(u32 addr, u32* val) bool ARMv5::DataRead32(u32 addr, u32* val) { + Store = false; if (!(PU_Map[addr>>12] & 0x01)) [[unlikely]] { DataAbort(); @@ -871,16 +914,27 @@ bool ARMv5::DataRead32(u32 addr, u32* val) if (addr < ITCMSize) { DataCycles = 1; + DataRegion = Mem9_ITCM; *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; + DataRegion = Mem9_DTCM; *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; return true; } + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; + *val = BusRead32(addr); DataCycles = MemTimings[addr >> 12][2]; return true; @@ -899,23 +953,36 @@ bool ARMv5::DataRead32S(u32 addr, u32* val) if (addr < ITCMSize) { DataCycles += 1; + DataRegion = Mem9_ITCM; *val = *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)]; return true; } if ((addr & DTCMMask) == DTCMBase) { DataCycles += 1; + DataRegion = Mem9_DTCM; *val = *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)]; return true; } + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; + *val = BusRead32(addr); - DataCycles += MemTimings[addr >> 12][3]; + NDS.ARM9Timestamp += DataCycles; + DataCycles = MemTimings[addr >> 12][3]; return true; } bool ARMv5::DataWrite8(u32 addr, u8 val) { + Store = true; if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]] { DataAbort(); @@ -925,6 +992,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val) if (addr < ITCMSize) { DataCycles = 1; + DataRegion = Mem9_ITCM; *(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); return true; @@ -932,10 +1000,20 @@ bool ARMv5::DataWrite8(u32 addr, u8 val) if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; + DataRegion = Mem9_DTCM; *(u8*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; return true; } + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; + BusWrite8(addr, val); DataCycles = MemTimings[addr >> 12][1]; return true; @@ -943,6 +1021,7 @@ bool ARMv5::DataWrite8(u32 addr, u8 val) bool ARMv5::DataWrite16(u32 addr, u16 val) { + Store = true; if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]] { DataAbort(); @@ -954,6 +1033,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val) if (addr < ITCMSize) { DataCycles = 1; + DataRegion = Mem9_ITCM; *(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); return true; @@ -961,10 +1041,20 @@ bool ARMv5::DataWrite16(u32 addr, u16 val) if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; + DataRegion = Mem9_DTCM; *(u16*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; return true; } + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; + BusWrite16(addr, val); DataCycles = MemTimings[addr >> 12][1]; return true; @@ -972,6 +1062,7 @@ bool ARMv5::DataWrite16(u32 addr, u16 val) bool ARMv5::DataWrite32(u32 addr, u32 val) { + Store = true; if (!(PU_Map[addr>>12] & 0x02)) [[unlikely]] { DataAbort(); @@ -983,6 +1074,7 @@ bool ARMv5::DataWrite32(u32 addr, u32 val) if (addr < ITCMSize) { DataCycles = 1; + DataRegion = Mem9_ITCM; *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); return true; @@ -990,10 +1082,20 @@ bool ARMv5::DataWrite32(u32 addr, u32 val) if ((addr & DTCMMask) == DTCMBase) { DataCycles = 1; + DataRegion = Mem9_DTCM; *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; return true; } + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; + BusWrite32(addr, val); DataCycles = MemTimings[addr >> 12][2]; return true; @@ -1012,6 +1114,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, bool dataabort) if (addr < ITCMSize) { DataCycles += 1; + DataRegion = Mem9_ITCM; *(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val; #ifdef JIT_ENABLED NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr); @@ -1021,10 +1124,20 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val, bool dataabort) if ((addr & DTCMMask) == DTCMBase) { DataCycles += 1; + DataRegion = Mem9_DTCM; *(u32*)&DTCM[addr & (DTCMPhysicalSize - 1)] = val; return true; } + NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<> 24) == 0x02) + { + if (NDS.ARM9Timestamp < MainRAMTimestamp) NDS.ARM9Timestamp = MainRAMTimestamp; + DataRegion = Mem9_MainRAM; + } + else DataRegion = NDS.ARM9Regions[addr>>14]; + BusWrite32(addr, val); DataCycles += MemTimings[addr >> 12][3]; return true;