diff --git a/src/ARM.cpp b/src/ARM.cpp index 83d58217..75dde763 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -218,6 +218,7 @@ void ARMv5::Reset() WBReleaseTS = 0; WBLastRegion = Mem9_Null; WBWriting = false; + WBInitialTS = 0; ARM::Reset(); } diff --git a/src/ARM.h b/src/ARM.h index d45d87b6..2a002df9 100644 --- a/src/ARM.h +++ b/src/ARM.h @@ -681,7 +681,7 @@ public: u8 WBWritePointer; // which entry to attempt to write next; should always be ANDed with 0xF after incrementing u8 WBFillPointer; // where the next entry should be added; should always be ANDed with 0xF after incrementing - bool WBWriting; // whether the buffer is actively trying to perform a write + u8 WBWriting; // whether the buffer is actively trying to perform a write u32 WBCurAddr; // address the write buffer is currently writing to u64 WBCurVal; // current value being written; 0-31: val | 61-63: flag; 0 = byte ns; 1 = halfword ns; 2 = word ns; 3 = word s; 4 = address (invalid in this variable) u32 storeaddr[16]; // temp until i figure out why using the fifo address entries directly didn't work @@ -691,6 +691,7 @@ public: u64 WBDelay; // timestamp in bus cycles use for the delay before next write to the write buffer can occur (seems to be a 1 cycle delay after a write to it) u32 WBLastRegion; // the last region written to by the write buffer u64 WBReleaseTS; // the timestamp on which the write buffer relinquished control of the bus back + u64 WBInitialTS; // what cycle the entry was first sent in #ifdef GDBSTUB_ENABLED u32 ReadMem(u32 addr, int size) override; diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp index d2a8a9c7..7b8f93b0 100644 --- a/src/ARMInterpreter.cpp +++ b/src/ARMInterpreter.cpp @@ -293,7 +293,8 @@ void A_MCR(ARM* cpu) return A_UNK(cpu); // TODO: check what kind of exception it really is } - cpu->AddCycles_CI(1 + 1); // TODO: checkme + if (cpu->Num==0) cpu->AddCycles_CI(6); // checkme + else /* ARM7 */ cpu->AddCycles_CI(1 + 1); // TODO: checkme } void A_MRC(ARM* cpu) diff --git a/src/CP15.cpp b/src/CP15.cpp index fe79bad8..6c4af0ac 100644 --- a/src/CP15.cpp +++ b/src/CP15.cpp @@ -780,7 +780,8 @@ u32 ARMv5::DCacheLookup(const u32 addr) else { DataRegion = NDS.ARM9Regions[addr>>14]; - if ((NDS.ARM9Timestamp <= WBTimestamp-1) && (DataRegion == WBLastRegion)) // check write buffer + if (((NDS.ARM9Timestamp <= WBReleaseTS) && (NDS.ARM9Regions[addr>>14] == WBLastRegion)) // check write buffer + || (Store && (NDS.ARM9Regions[addr>>14] == DataRegion))) //check the actual store NDS.ARM9Timestamp += 1<>14] == Mem9_MainRAM) && (((MainRAMTimestamp + ((1< WBTimestamp)) + WBTimestamp = (MainRAMTimestamp + ((1<> 61) != 3) && (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM)) - ts = std::max(WBTimestamp, MainRAMTimestamp); - else - ts = WBTimestamp; - - if ((WBCurVal >> 61) != 3) ts = (ts + ((1< NDS.ARM9Timestamp) return true; if ( force && ts > NDS.ARM9Timestamp) @@ -1245,6 +1241,7 @@ inline bool ARMv5::WriteBufferHandle() WBTimestamp = ts; if (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM) MainRAMTimestamp += 2 << NDS.ARM9ClockShift; } + WBInitialTS = WBTimestamp; switch (WBCurVal >> 61) { @@ -1275,11 +1272,15 @@ inline bool ARMv5::WriteBufferHandle() { if (NDS.ARM9Regions[storeaddr[WBWritePointer]>>14] == Mem9_MainRAM) // main ram handling { - if (!force && (MainRAMTimestamp > NDS.ARM9Timestamp)) return true; - if ( force && (MainRAMTimestamp > NDS.ARM9Timestamp)) - NDS.ARM9Timestamp = MainRAMTimestamp; + if (!force && (WBTimestamp > NDS.ARM9Timestamp)) return true; + if ( force && (WBTimestamp > NDS.ARM9Timestamp)) + NDS.ARM9Timestamp = WBTimestamp; + + WBTimestamp = std::max(MainRAMTimestamp, WBTimestamp); } + WBTimestamp = (WBTimestamp + ((1<()); // loop until we've cleared out all writeable entries - if constexpr (next == 1) // check if the next write is occuring + if constexpr (next == 1 || next == 3) // check if the next write is occuring { - if (WBWriting) + if (NDS.ARM9Timestamp >= WBInitialTS)// + (NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM)))// || ((NDS.ARM9Regions[WBCurAddr>>14] == Mem9_MainRAM) && WBWriting)) { + u64 tsold = NDS.ARM9Timestamp; while(!WriteBufferHandle<2>()); + + //if constexpr (next == 3) NDS.ARM9Timestamp = std::max(tsold, NDS.ARM9Timestamp - (2<()); + //if (NDS.ARM9Timestamp >= WBInitialTS) + while(!WriteBufferHandle<2>()); } } +template void ARMv5::WriteBufferCheck<3>(); template void ARMv5::WriteBufferCheck<2>(); template void ARMv5::WriteBufferCheck<1>(); template void ARMv5::WriteBufferCheck<0>(); @@ -1326,10 +1331,14 @@ void ARMv5::WriteBufferWrite(u32 val, u8 flag, u32 addr) if (WBFillPointer == WBWritePointer) // if the write buffer is full then we stall the cpu until room is made WriteBufferHandle<1>(); - else if (WBWritePointer == 16) // indicates empty write buffer + else if (WBWritePointer == 16 && (flag != 4)) // indicates empty write buffer { WBWritePointer = 0; - if (!WBWriting && (WBTimestamp < (NDS.ARM9Timestamp+1))) WBTimestamp = (NDS.ARM9Timestamp+1); + u64 ts = (NDS.ARM9Regions[addr>>14] == Mem9_MainRAM) ? std::max(MainRAMTimestamp, NDS.ARM9Timestamp + 1) : NDS.ARM9Timestamp + 1; + + if (!WBWriting && (WBTimestamp < ((ts + ((1<>12] & 0x30) WriteBufferDrain(); else - WriteBufferCheck<1>(); + WriteBufferCheck<3>(); NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<>14]; - WBTimestamp = NDS.ARM9Timestamp; + if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<>14]; - WBTimestamp = NDS.ARM9Timestamp; + if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<>14]; - WBTimestamp = NDS.ARM9Timestamp; + if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<>14][1]; if ((addr >> 24) == 0x02) @@ -2851,7 +2871,8 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val) else DataRegion = NDS.ARM9Regions[addr>>14]; } - WBTimestamp = NDS.ARM9Timestamp; + if (WBTimestamp < ((NDS.ARM9Timestamp + DataCycles + ((1<