Merge branch 'less-ambitious-timing-rework' into chemical-x
This commit is contained in:
commit
9f3ebeafa7
|
@ -211,6 +211,7 @@ void ARMv5::Reset()
|
|||
WBWritePointer = 16;
|
||||
WBFillPointer = 0;
|
||||
WBDelay = 0;
|
||||
WBWriting = false;
|
||||
|
||||
ARM::Reset();
|
||||
}
|
||||
|
|
21
src/ARM.h
21
src/ARM.h
|
@ -403,6 +403,7 @@ public:
|
|||
*/
|
||||
void ICacheInvalidateAll();
|
||||
|
||||
template <bool force> inline bool WriteBufferHandle();
|
||||
void WriteBufferCheck();
|
||||
void WriteBufferWrite(u32 val, u8 flag, u8 cycles, u32 addr = 0);
|
||||
void WriteBufferDrain();
|
||||
|
@ -681,13 +682,19 @@ public:
|
|||
bool Store;
|
||||
u16 InterlockMask;
|
||||
|
||||
u8 WBWritePointer;
|
||||
u8 WBFillPointer;
|
||||
u64 WBDelay;
|
||||
u32 WBAddr; // current working address for the write buffer
|
||||
u32 storeaddr[16]; // debugging
|
||||
u64 WBCycles[16]; // timestamp each write will complete
|
||||
u64 WriteBufferFifo[16]; // 0-31: value | 62-63: 0 byte, 1 half, 2 word, 3 addr
|
||||
|
||||
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 WBCurCycles; // how long the current write will take; bit 7 is a flag used to indicate main ram
|
||||
u64 WBCurVal; // current value being written; 0-31: val | 62-32: flag; 0 = byte; 1 = halfword; 2 = word; 3 = address (invalid in this variable)
|
||||
u32 WBCurAddr; // address the write buffer is currently writing to
|
||||
u32 storeaddr[16]; // temp until i figure out why using the fifo address entries directly didn't work
|
||||
u8 WBCycles[16]; // num cycles for each write; bit 7 is a flag used to indicate main ram
|
||||
u64 WriteBufferFifo[16]; // 0-31: val | 62-32: flag; 0 = byte; 1 = halfword; 2 = word; 3 = address
|
||||
u64 WBTimestamp; // current timestamp in bus cycles
|
||||
u64 WBMainRAMDelay; // timestamp in bus cycles used to emulate the delay before the next main ram write can begin
|
||||
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)
|
||||
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
u32 ReadMem(u32 addr, int size) override;
|
||||
|
|
263
src/CP15.cpp
263
src/CP15.cpp
|
@ -957,159 +957,109 @@ bool ARMv5::IsAddressDCachable(const u32 addr) const
|
|||
return PU_Map[addr >> CP15_MAP_ENTRYSIZE_LOG2] & CP15_MAP_DCACHEABLE;
|
||||
}
|
||||
|
||||
template <bool force>
|
||||
inline bool ARMv5::WriteBufferHandle()
|
||||
{
|
||||
// handle write buffer writes
|
||||
if (WBWriting)
|
||||
{
|
||||
bool mainram = (WBCurCycles >= 0x80);
|
||||
|
||||
u64 ts;
|
||||
if (mainram) ts = std::max(WBTimestamp, WBMainRAMDelay) + (WBCurCycles & 0x7F);
|
||||
else ts = WBTimestamp + (WBCurCycles & 0x7F);
|
||||
|
||||
if (!force && ts > ((NDS.ARM9Timestamp + DataCycles) >> NDS.ARM9ClockShift)) return true;
|
||||
if ( force && ts > ((NDS.ARM9Timestamp + DataCycles) >> NDS.ARM9ClockShift))
|
||||
{
|
||||
NDS.ARM9Timestamp = ((ts - 1) << NDS.ARM9ClockShift) + 1;
|
||||
DataCycles = 0; // checkme
|
||||
}
|
||||
|
||||
WBTimestamp = ts;
|
||||
if (mainram) WBMainRAMDelay = WBTimestamp + 2;
|
||||
|
||||
switch (WBCurVal >> 62)
|
||||
{
|
||||
case 0: // byte
|
||||
BusWrite8 (WBCurAddr, WBCurVal);
|
||||
break;
|
||||
case 1: // halfword
|
||||
BusWrite16(WBCurAddr, WBCurVal);
|
||||
break;
|
||||
case 2: // word
|
||||
BusWrite32(WBCurAddr, WBCurVal);
|
||||
break;
|
||||
default: // address ie. invalid
|
||||
Platform::Log(Platform::LogLevel::Warn, "WHY ARE WE TRYING TO WRITE AN ADDRESS VIA THE WRITE BUFFER! PANIC!!!\n", (u8)(WBCurVal >> 62));
|
||||
break;
|
||||
}
|
||||
|
||||
//printf("writing: adr: %i, val: %lli, cyl: %i", WBCurAddr, WBCurVal, WBCurCycles);
|
||||
WBWriting = false;
|
||||
}
|
||||
|
||||
// check if write buffer is empty
|
||||
if (WBWritePointer == 16) return true;
|
||||
// attempt to drain write buffer
|
||||
if ((WriteBufferFifo[WBWritePointer] >> 62) != 3) // not an address
|
||||
{
|
||||
if (WBCycles[WBWritePointer] >= 0x80) // main ram handling
|
||||
{
|
||||
u64 ts = ((NDS.ARM9Timestamp + DataCycles) >> NDS.ARM9ClockShift);
|
||||
if (!force && (WBMainRAMDelay > ts)) return true;
|
||||
if ( force && (WBMainRAMDelay > ts))
|
||||
{
|
||||
NDS.ARM9Timestamp = ((WBMainRAMDelay - 1) << NDS.ARM9ClockShift) + 1;
|
||||
DataCycles = 0;
|
||||
}
|
||||
}
|
||||
|
||||
WBCurVal = WriteBufferFifo[WBWritePointer];
|
||||
WBCurCycles = WBCycles[WBWritePointer];
|
||||
WBCurAddr = storeaddr[WBWritePointer];
|
||||
WBWriting = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// todo: i want to set the address here instead
|
||||
}
|
||||
|
||||
WBWritePointer = (WBWritePointer + 1) & 0xF;
|
||||
if (WBWritePointer == WBFillPointer)
|
||||
{
|
||||
WBWritePointer = 16;
|
||||
WBFillPointer = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ARMv5::WriteBufferCheck()
|
||||
{
|
||||
if (WBWritePointer == 16) return;
|
||||
|
||||
while (WBCycles[WBWritePointer] <= (NDS.ARM9Timestamp + DataCycles))
|
||||
{
|
||||
//printf("drainingwb %lli, %i %08X %i\n", WBCycles[WBWritePointer], WBWritePointer, WBAddr, WriteBufferFifo[WBWritePointer] >> 62);
|
||||
switch ((u64)WriteBufferFifo[WBWritePointer] >> 62)
|
||||
{
|
||||
case 0: // byte
|
||||
{
|
||||
u8 val = WriteBufferFifo[WBWritePointer] & 0xFF;
|
||||
BusWrite8(storeaddr[WBWritePointer], val);
|
||||
break;
|
||||
}
|
||||
case 1: // halfword
|
||||
{
|
||||
u16 val = WriteBufferFifo[WBWritePointer] & 0xFFFF;
|
||||
BusWrite16(storeaddr[WBWritePointer], val);
|
||||
break;
|
||||
}
|
||||
case 2: // word
|
||||
{
|
||||
u32 val = WriteBufferFifo[WBWritePointer] & 0xFFFFFFFF;
|
||||
BusWrite32(storeaddr[WBWritePointer], val);
|
||||
WBAddr += 4;
|
||||
break;
|
||||
}
|
||||
case 3: // address update
|
||||
WBAddr = WriteBufferFifo[WBWritePointer] & 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
WBWritePointer = (WBWritePointer + 1) & 0xF;
|
||||
if (WBWritePointer == WBFillPointer)
|
||||
{
|
||||
WBWritePointer = 16;
|
||||
WBFillPointer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!WriteBufferHandle<false>()); // loop until we've cleared out all writeable entries
|
||||
}
|
||||
|
||||
void ARMv5::WriteBufferWrite(u32 val, u8 flag, u8 cycles, u32 addr)
|
||||
{
|
||||
WriteBufferCheck();
|
||||
|
||||
if (WBFillPointer == WBWritePointer)
|
||||
if (WBFillPointer == WBWritePointer) // if the write buffer is full then we stall the cpu until room is made
|
||||
WriteBufferHandle<true>();
|
||||
else if (WBWritePointer == 16) // indicates empty write buffer
|
||||
{
|
||||
//printf("forcedrainingwb %lli, %i %08X %i\n", WBCycles[WBWritePointer], WBWritePointer, WBAddr, WriteBufferFifo[WBWritePointer] >> 62);
|
||||
if (NDS.ARM9Timestamp < WBCycles[WBWritePointer])
|
||||
{
|
||||
NDS.ARM9Timestamp = WBCycles[WBWritePointer];
|
||||
DataCycles = 0; // checkme
|
||||
}
|
||||
|
||||
switch ((u64)WriteBufferFifo[WBWritePointer] >> 62)
|
||||
{
|
||||
case 0: // byte
|
||||
{
|
||||
u8 val = WriteBufferFifo[WBWritePointer] & 0xFF;
|
||||
BusWrite8(storeaddr[WBWritePointer], val);
|
||||
break;
|
||||
}
|
||||
case 1: // halfword
|
||||
{
|
||||
u16 val = WriteBufferFifo[WBWritePointer] & 0xFFFF;
|
||||
BusWrite16(storeaddr[WBWritePointer], val);
|
||||
break;
|
||||
}
|
||||
case 2: // word
|
||||
{
|
||||
u32 val = WriteBufferFifo[WBWritePointer] & 0xFFFFFFFF;
|
||||
BusWrite32(storeaddr[WBWritePointer], val);
|
||||
WBAddr += 4;
|
||||
break;
|
||||
}
|
||||
case 3: // address update
|
||||
WBAddr = WriteBufferFifo[WBWritePointer] & 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
WBWritePointer = (WBWritePointer + 1) & 0xF;
|
||||
if (WBWritePointer == WBFillPointer)
|
||||
{
|
||||
WBWritePointer = 16;
|
||||
WBFillPointer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("fillingwb %lli %i %i %08X %i\n", NDS.ARM9Timestamp, WBWritePointer, WBFillPointer, val, flag);
|
||||
if (WBWritePointer == 16)
|
||||
{
|
||||
WBCycles[WBFillPointer] = NDS.ARM9Timestamp + DataCycles + cycles;
|
||||
WBWritePointer = 0;
|
||||
WBTimestamp = (((NDS.ARM9Timestamp + DataCycles) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
}
|
||||
else
|
||||
{
|
||||
WBCycles[WBFillPointer] = WBCycles[(WBFillPointer-1) & 0xF] + cycles;
|
||||
}
|
||||
|
||||
WriteBufferFifo[WBFillPointer] = val | (u64)flag << 62;
|
||||
WBCycles[WBFillPointer] = cycles;
|
||||
storeaddr[WBFillPointer] = addr;
|
||||
WBFillPointer = (WBFillPointer + 1) & 0xF;
|
||||
}
|
||||
|
||||
void ARMv5::WriteBufferDrain()
|
||||
{
|
||||
if (WBWritePointer == 16) return;
|
||||
|
||||
while (true)
|
||||
{
|
||||
//printf("fullydrainingwb %lli, %i %08X %i\n", WBCycles[WBWritePointer], WBWritePointer, WBAddr, WriteBufferFifo[WBWritePointer] >> 62);
|
||||
if (NDS.ARM9Timestamp < WBCycles[WBWritePointer])
|
||||
{
|
||||
NDS.ARM9Timestamp = WBCycles[WBWritePointer];
|
||||
DataCycles = 0; // checkme
|
||||
}
|
||||
|
||||
switch (WriteBufferFifo[WBWritePointer] >> 62)
|
||||
{
|
||||
case 0: // byte
|
||||
{
|
||||
u8 val = WriteBufferFifo[WBWritePointer] & 0xFF;
|
||||
BusWrite8(storeaddr[WBWritePointer], val);
|
||||
break;
|
||||
}
|
||||
case 1: // halfword
|
||||
{
|
||||
u16 val = WriteBufferFifo[WBWritePointer] & 0xFFFF;
|
||||
BusWrite16(storeaddr[WBWritePointer], val);
|
||||
break;
|
||||
}
|
||||
case 2: // word
|
||||
{
|
||||
u32 val = WriteBufferFifo[WBWritePointer] & 0xFFFFFFFF;
|
||||
BusWrite32(storeaddr[WBWritePointer], val);
|
||||
WBAddr += 4;
|
||||
break;
|
||||
}
|
||||
case 3: // address update
|
||||
WBAddr = WriteBufferFifo[WBWritePointer] & 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
|
||||
WBWritePointer = (WBWritePointer + 1) & 0xF;
|
||||
if (WBWritePointer == WBFillPointer)
|
||||
{
|
||||
WBWritePointer = 16;
|
||||
WBFillPointer = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//printf("wbdrained\n");
|
||||
while (!WriteBufferHandle<true>()); // loop until drained fully
|
||||
}
|
||||
|
||||
void ARMv5::CP15Write(u32 id, u32 val)
|
||||
|
@ -2217,9 +2167,16 @@ bool ARMv5::DataWrite8(u32 addr, u8 val)
|
|||
else
|
||||
{
|
||||
if (WBDelay > NDS.ARM9Timestamp) NDS.ARM9Timestamp = WBDelay;
|
||||
|
||||
u8 cycles = NDS.ARM9MemTimings[addr>>14][0];
|
||||
if ((addr >> 24) == 0x02)
|
||||
{
|
||||
cycles = (cycles - 2) & 0x80;
|
||||
}
|
||||
|
||||
WriteBufferWrite(addr, 3, 0);
|
||||
WriteBufferWrite(val, 0, cycles, addr);
|
||||
DataCycles = 1;
|
||||
WriteBufferWrite(addr, 3, 1);
|
||||
WriteBufferWrite(val, 0, MemTimings[addr >> 12][1], addr);
|
||||
WBDelay = NDS.ARM9Timestamp + 2;
|
||||
}
|
||||
return true;
|
||||
|
@ -2293,9 +2250,16 @@ bool ARMv5::DataWrite16(u32 addr, u16 val)
|
|||
else
|
||||
{
|
||||
if (WBDelay > NDS.ARM9Timestamp) NDS.ARM9Timestamp = WBDelay;
|
||||
|
||||
u8 cycles = NDS.ARM9MemTimings[addr>>14][0];
|
||||
if ((addr >> 24) == 0x02)
|
||||
{
|
||||
cycles = (cycles - 2) & 0x80;
|
||||
}
|
||||
|
||||
WriteBufferWrite(addr, 3, 0);
|
||||
WriteBufferWrite(val, 1, cycles, addr);
|
||||
DataCycles = 1;
|
||||
WriteBufferWrite(addr, 3, 1);
|
||||
WriteBufferWrite(val, 1, MemTimings[addr >> 12][1], addr);
|
||||
WBDelay = NDS.ARM9Timestamp + 2;
|
||||
}
|
||||
return true;
|
||||
|
@ -2370,9 +2334,16 @@ bool ARMv5::DataWrite32(u32 addr, u32 val)
|
|||
else
|
||||
{
|
||||
if (WBDelay > NDS.ARM9Timestamp) NDS.ARM9Timestamp = WBDelay;
|
||||
|
||||
u8 cycles = NDS.ARM9MemTimings[addr>>14][2];
|
||||
if ((addr >> 24) == 0x02)
|
||||
{
|
||||
cycles = (cycles - 2) & 0x80;
|
||||
}
|
||||
|
||||
WriteBufferWrite(addr, 3, 0);
|
||||
WriteBufferWrite(val, 2, cycles, addr);
|
||||
DataCycles = 1;
|
||||
WriteBufferWrite(addr, 3, 1);
|
||||
WriteBufferWrite(val, 2, MemTimings[addr >> 12][2], addr);
|
||||
WBDelay = NDS.ARM9Timestamp + 2;
|
||||
}
|
||||
return true;
|
||||
|
@ -2427,7 +2398,7 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val)
|
|||
|
||||
if (!(PU_Map[addr>>12] & 0x30))
|
||||
{
|
||||
DataCycles += (((NDS.ARM9Timestamp + DataCycles) + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1)) - (NDS.ARM9Timestamp + DataCycles));
|
||||
DataCycles += (((NDS.ARM9Timestamp + DataCycles) + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1))) - (NDS.ARM9Timestamp + DataCycles);
|
||||
|
||||
if (!(addr & 0x3FF)) return DataWrite32(addr, val); // bursts cannot cross a 1kb boundary
|
||||
|
||||
|
@ -2444,8 +2415,14 @@ bool ARMv5::DataWrite32S(u32 addr, u32 val)
|
|||
}
|
||||
else
|
||||
{
|
||||
u8 cycles = NDS.ARM9MemTimings[addr>>14][3];
|
||||
if ((addr >> 24) == 0x02)
|
||||
{
|
||||
cycles = (cycles - 2) & 0x80;
|
||||
}
|
||||
|
||||
WriteBufferWrite(val, 2, cycles, addr);
|
||||
DataCycles += 1;
|
||||
WriteBufferWrite(val, 2, MemTimings[addr >> 12][3], addr);
|
||||
WBDelay = NDS.ARM9Timestamp + DataCycles + 1;
|
||||
}
|
||||
return true;
|
||||
|
|
Loading…
Reference in New Issue