Idle skipping... maybe?
This commit is contained in:
@@ -20,6 +20,7 @@ vgcore.*
|
|||||||
*.data
|
*.data
|
||||||
disasm.txt
|
disasm.txt
|
||||||
*log*.txt
|
*log*.txt
|
||||||
|
*.log
|
||||||
CMakeSettings.json
|
CMakeSettings.json
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
*.diagsession
|
*.diagsession
|
||||||
|
|||||||
@@ -110,6 +110,15 @@ void Core::Run(const float volumeL, const float volumeR) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (cycles < mem->mmio.vi.cyclesPerHalfline) {
|
while (cycles < mem->mmio.vi.cyclesPerHalfline) {
|
||||||
|
if (IsAnythingSkippable()) {
|
||||||
|
const u32 taken = Scheduler::GetInstance().events.top().time - Scheduler::GetInstance().ticks;
|
||||||
|
cycles += taken;
|
||||||
|
frameCycles += taken;
|
||||||
|
Scheduler::GetInstance().Tick(taken);
|
||||||
|
isReadingAnyIO = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const u32 taken = StepCPU();
|
const u32 taken = StepCPU();
|
||||||
cycles += taken;
|
cycles += taken;
|
||||||
|
|
||||||
@@ -141,4 +150,9 @@ void Core::Run(const float volumeL, const float volumeR) {
|
|||||||
if (broken)
|
if (broken)
|
||||||
pause = true;
|
pause = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Core::IsAnythingSkippable() {
|
||||||
|
MMIO &mmio = mem->mmio;
|
||||||
|
return (mmio.si.status.dmaBusy || mmio.pi.dmaBusy || mmio.pi.ioBusy) && isReadingAnyIO;
|
||||||
|
}
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ struct Core {
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SetIdleSkippingStatus(bool v) { GetInstance().isReadingAnyIO = v; }
|
||||||
|
|
||||||
static Registers &GetRegs() { return GetInstance().regs; }
|
static Registers &GetRegs() { return GetInstance().regs; }
|
||||||
|
|
||||||
static Mem &GetMem() { return *GetInstance().mem; }
|
static Mem &GetMem() { return *GetInstance().mem; }
|
||||||
@@ -57,5 +59,8 @@ struct Core {
|
|||||||
#endif
|
#endif
|
||||||
Interpreter interpreter;
|
Interpreter interpreter;
|
||||||
ParallelRDP parallel;
|
ParallelRDP parallel;
|
||||||
|
|
||||||
|
bool isReadingAnyIO = false;
|
||||||
|
bool IsAnythingSkippable();
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
+466
-462
File diff suppressed because it is too large
Load Diff
@@ -3,35 +3,35 @@
|
|||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct PI {
|
struct PI {
|
||||||
PI();
|
PI();
|
||||||
void Reset();
|
void Reset();
|
||||||
[[nodiscard]] auto Read(u32) const -> u32;
|
[[nodiscard]] auto Read(u32) const -> u32;
|
||||||
void Write(u32, u32);
|
void Write(u32, u32);
|
||||||
|
|
||||||
template <typename T, bool isDma>
|
template <typename T, bool isDma>
|
||||||
void BusWrite(u32, u32);
|
void BusWrite(u32, u32);
|
||||||
template <bool isDma>
|
template <bool isDma>
|
||||||
void BusWrite(u32, u64);
|
void BusWrite(u32, u64);
|
||||||
|
|
||||||
template <typename T, bool isDma>
|
template <typename T, bool isDma>
|
||||||
auto BusRead(u32) -> T;
|
auto BusRead(u32) -> T;
|
||||||
|
|
||||||
bool ReadLatch();
|
bool ReadLatch();
|
||||||
bool WriteLatch(u32 val);
|
bool WriteLatch(u32 val);
|
||||||
|
|
||||||
static u8 GetDomain(u32 address);
|
static u8 GetDomain(u32 address);
|
||||||
[[nodiscard]] u32 AccessTiming(u8 domain, u32 length) const;
|
[[nodiscard]] u32 AccessTiming(u8 domain, u32 length) const;
|
||||||
bool dmaBusy{}, ioBusy{};
|
bool dmaBusy{}, ioBusy{};
|
||||||
u32 latch{};
|
u32 latch{};
|
||||||
u32 dramAddr{}, cartAddr{};
|
u32 dramAddr{}, cartAddr{};
|
||||||
u32 rdLen{}, wrLen{};
|
u32 rdLen{}, wrLen{};
|
||||||
u32 piBsdDom1Lat{}, piBsdDom2Lat{};
|
u32 piBsdDom1Lat{}, piBsdDom2Lat{};
|
||||||
u32 piBsdDom1Pwd{}, piBsdDom2Pwd{};
|
u32 piBsdDom1Pwd{}, piBsdDom2Pwd{};
|
||||||
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
|
u32 piBsdDom1Pgs{}, piBsdDom2Pgs{};
|
||||||
u32 piBsdDom1Rls{}, piBsdDom2Rls{};
|
u32 piBsdDom1Rls{}, piBsdDom2Rls{};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <bool toDram>
|
template <bool toDram>
|
||||||
void DMA();
|
void DMA();
|
||||||
};
|
};
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -5,91 +5,92 @@ namespace n64 {
|
|||||||
SI::SI() { Reset(); }
|
SI::SI() { Reset(); }
|
||||||
|
|
||||||
void SI::Reset() {
|
void SI::Reset() {
|
||||||
status.raw = 0;
|
status.raw = 0;
|
||||||
dramAddr = 0;
|
dramAddr = 0;
|
||||||
pifAddr = 0;
|
pifAddr = 0;
|
||||||
toDram = false;
|
toDram = false;
|
||||||
pif.Reset();
|
pif.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto SI::Read(u32 addr) const -> u32 {
|
auto SI::Read(u32 addr) const -> u32 {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x04800000:
|
case 0x04800000:
|
||||||
return dramAddr;
|
return dramAddr;
|
||||||
case 0x04800004:
|
case 0x04800004:
|
||||||
case 0x04800010:
|
case 0x04800010:
|
||||||
return pifAddr;
|
return pifAddr;
|
||||||
case 0x0480000C:
|
case 0x0480000C:
|
||||||
return 0;
|
return 0;
|
||||||
case 0x04800018:
|
case 0x04800018:
|
||||||
{
|
{
|
||||||
u32 val = 0;
|
Core::SetIdleSkippingStatus(true);
|
||||||
val |= status.dmaBusy;
|
u32 val = 0;
|
||||||
val |= (0 << 1);
|
val |= status.dmaBusy;
|
||||||
val |= (0 << 3);
|
val |= (0 << 1);
|
||||||
val |= (mem.mmio.mi.intr.si << 12);
|
val |= (0 << 3);
|
||||||
return val;
|
val |= (mem.mmio.mi.intr.si << 12);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic("Unhandled SI[{:08X}] read", addr);
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
panic("Unhandled SI[{:08X}] read", addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pif -> rdram
|
// pif -> rdram
|
||||||
template <>
|
template <>
|
||||||
void SI::DMA<true>() {
|
void SI::DMA<true>() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
pif.ProcessCommands();
|
pif.ProcessCommands();
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
|
mem.mmio.rdp.WriteRDRAM<u8>(dramAddr + i, pif.Read(pifAddr + i));
|
||||||
}
|
}
|
||||||
trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
|
trace("SI DMA from PIF RAM to RDRAM ({:08X} to {:08X})", pifAddr, dramAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// rdram -> pif
|
// rdram -> pif
|
||||||
template <>
|
template <>
|
||||||
void SI::DMA<false>() {
|
void SI::DMA<false>() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
for (int i = 0; i < 64; i++) {
|
for (int i = 0; i < 64; i++) {
|
||||||
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
|
pif.Write(pifAddr + i, mem.mmio.rdp.ReadRDRAM<u8>(dramAddr + i));
|
||||||
}
|
}
|
||||||
trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
|
trace("SI DMA from RDRAM to PIF RAM ({:08X} to {:08X})", dramAddr, pifAddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SI::DMA() {
|
void SI::DMA() {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
status.dmaBusy = false;
|
status.dmaBusy = false;
|
||||||
if (toDram)
|
if (toDram)
|
||||||
DMA<true>();
|
DMA<true>();
|
||||||
else
|
else
|
||||||
DMA<false>();
|
DMA<false>();
|
||||||
mem.mmio.mi.InterruptRaise(MI::Interrupt::SI);
|
mem.mmio.mi.InterruptRaise(MI::Interrupt::SI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SI::Write(u32 addr, u32 val) {
|
void SI::Write(u32 addr, u32 val) {
|
||||||
n64::Mem& mem = n64::Core::GetMem();
|
n64::Mem &mem = n64::Core::GetMem();
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
case 0x04800000:
|
case 0x04800000:
|
||||||
dramAddr = val & RDRAM_DSIZE;
|
dramAddr = val & RDRAM_DSIZE;
|
||||||
break;
|
break;
|
||||||
case 0x04800004:
|
case 0x04800004:
|
||||||
pifAddr = val & 0x1FFFFFFF;
|
pifAddr = val & 0x1FFFFFFF;
|
||||||
status.dmaBusy = true;
|
status.dmaBusy = true;
|
||||||
toDram = true;
|
toDram = true;
|
||||||
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
|
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
|
||||||
break;
|
break;
|
||||||
case 0x04800010:
|
case 0x04800010:
|
||||||
pifAddr = val & 0x1FFFFFFF;
|
pifAddr = val & 0x1FFFFFFF;
|
||||||
status.dmaBusy = true;
|
status.dmaBusy = true;
|
||||||
toDram = false;
|
toDram = false;
|
||||||
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
|
Scheduler::GetInstance().EnqueueRelative(SI_DMA_DELAY, SI_DMA);
|
||||||
break;
|
break;
|
||||||
case 0x04800018:
|
case 0x04800018:
|
||||||
mem.mmio.mi.InterruptLower(MI::Interrupt::SI);
|
mem.mmio.mi.InterruptLower(MI::Interrupt::SI);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
panic("Unhandled SI[{:08X}] write ({:08X})", addr, val);
|
panic("Unhandled SI[{:08X}] write ({:08X})", addr, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace n64
|
} // namespace n64
|
||||||
|
|||||||
@@ -4,33 +4,32 @@
|
|||||||
#include <core/mmio/PIF.hpp>
|
#include <core/mmio/PIF.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
|
|
||||||
union SIStatus {
|
|
||||||
u32 raw{};
|
|
||||||
struct {
|
|
||||||
unsigned dmaBusy : 1;
|
|
||||||
unsigned ioBusy : 1;
|
|
||||||
unsigned reserved : 1;
|
|
||||||
unsigned dmaErr : 1;
|
|
||||||
unsigned : 8;
|
|
||||||
unsigned intr : 1;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SI {
|
struct SI {
|
||||||
SI();
|
SI();
|
||||||
void Reset();
|
void Reset();
|
||||||
[[nodiscard]] auto Read(u32) const -> u32;
|
[[nodiscard]] auto Read(u32) const -> u32;
|
||||||
void Write(u32, u32);
|
void Write(u32, u32);
|
||||||
template <bool toDram>
|
template <bool toDram>
|
||||||
void DMA();
|
void DMA();
|
||||||
void DMA();
|
void DMA();
|
||||||
|
|
||||||
bool toDram = false;
|
union Status {
|
||||||
SIStatus status{};
|
u32 raw{};
|
||||||
u32 dramAddr{};
|
struct {
|
||||||
u32 pifAddr{};
|
unsigned dmaBusy : 1;
|
||||||
PIF pif;
|
unsigned ioBusy : 1;
|
||||||
|
unsigned reserved : 1;
|
||||||
|
unsigned dmaErr : 1;
|
||||||
|
unsigned : 8;
|
||||||
|
unsigned intr : 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bool toDram = false;
|
||||||
|
Status status{};
|
||||||
|
u32 dramAddr{};
|
||||||
|
u32 pifAddr{};
|
||||||
|
PIF pif;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SI_DMA_DELAY (65536 * 2)
|
#define SI_DMA_DELAY (65536 * 2)
|
||||||
|
|||||||
Reference in New Issue
Block a user