prep cache impl

This commit is contained in:
2026-04-23 10:39:49 +02:00
parent 811b4d809c
commit 68e613057e
4 changed files with 133 additions and 110 deletions
+4
View File
@@ -0,0 +1,4 @@
CompileFlags:
CompilationDatabase: build/
Completion:
HeaderInsertion: Never
+91 -93
View File
@@ -5,132 +5,130 @@
namespace n64 { namespace n64 {
Core::Core() { Core::Core() {
const auto selectedCpu = Options::GetInstance().GetValue<std::string>("cpu", "type"); const auto selectedCpu = Options::GetInstance().GetValue<std::string>("cpu", "type");
if (selectedCpu == "interpreter") { if (selectedCpu == "interpreter") {
cpuType = Interpreted; cpuType = Interpreted;
cpu = std::make_unique<Interpreter>(*mem, regs); cpu = std::make_unique<Interpreter>(*mem, regs);
} else if(selectedCpu == "jit") { } else if (selectedCpu == "jit") {
#ifndef __aarch64__ #ifndef __aarch64__
cpuType = DynamicRecompiler; cpuType = DynamicRecompiler;
cpu = std::make_unique<JIT>(*mem, regs); cpu = std::make_unique<JIT>(*mem, regs);
#else #else
panic("JIT currently unsupported on aarch64"); panic("JIT currently unsupported on aarch64");
#endif #endif
} else { } else {
panic("Unimplemented CPU type"); panic("Unimplemented CPU type");
} }
} }
void Core::Stop() { void Core::Stop() {
pause = true; pause = true;
romLoaded = false; romLoaded = false;
Reset(); Reset();
} }
void Core::Reset() { void Core::Reset() {
regs.Reset(); regs.Reset();
mem->Reset(); mem->Reset();
cpu->Reset(); cpu->Reset();
if(romLoaded) if (romLoaded)
mem->mmio.si.pif.Execute(); mem->mmio.si.pif.Execute();
} }
void Core::LoadTAS(const fs::path &path) const { mem->mmio.si.pif.movie.Load(path); } void Core::LoadTAS(const fs::path &path) const { mem->mmio.si.pif.movie.Load(path); }
void Core::LoadROM(const std::string &rom_) { void Core::LoadROM(const std::string &rom_) {
Stop(); Stop();
rom = rom_; rom = rom_;
std::string archive_types[] = {".zip", ".7z", ".rar", ".tar"}; std::string archive_types[] = {".zip", ".7z", ".rar", ".tar"};
auto extension = fs::path(rom).extension().string(); auto extension = fs::path(rom).extension().string();
const bool isArchive = std::ranges::any_of(archive_types, [&extension](const auto &e) { return e == extension; }); const bool isArchive = std::ranges::any_of(archive_types, [&extension](const auto &e) { return e == extension; });
mem->LoadROM(isArchive, rom); mem->LoadROM(isArchive, rom);
GameDB::match(); GameDB::match();
if (mem->rom.gameNameDB.empty()) { if (mem->rom.gameNameDB.empty()) {
mem->rom.gameNameDB = fs::path(rom).stem().string(); mem->rom.gameNameDB = fs::path(rom).stem().string();
} }
mem->mmio.vi.isPal = mem->IsROMPAL(); mem->mmio.vi.isPal = mem->IsROMPAL();
mem->mmio.si.pif.InitDevices(mem->saveType); mem->mmio.si.pif.InitDevices(mem->saveType);
mem->mmio.si.pif.mempakPath = rom; mem->mmio.si.pif.mempakPath = rom;
mem->mmio.si.pif.LoadEeprom(mem->saveType, rom); mem->mmio.si.pif.LoadEeprom(mem->saveType, rom);
mem->flash.Load(mem->saveType, rom); mem->flash.Load(mem->saveType, rom);
mem->LoadSRAM(mem->saveType, rom); mem->LoadSRAM(mem->saveType, rom);
mem->mmio.si.pif.Execute(); mem->mmio.si.pif.Execute();
pause = false; pause = false;
romLoaded = true; romLoaded = true;
} }
u32 Core::StepCPU() { u32 Core::StepCPU() { return cpu->Step() + regs.PopStalledCycles(); }
return cpu->Step() + regs.PopStalledCycles();
}
void Core::StepRSP(const u32 cpuCycles) { void Core::StepRSP(const u32 cpuCycles) {
MMIO &mmio = mem->mmio; MMIO &mmio = mem->mmio;
if (mmio.rsp.spStatus.halt) { if (mmio.rsp.spStatus.halt) {
regs.steps = 0; regs.steps = 0;
mmio.rsp.steps = 0; mmio.rsp.steps = 0;
return; return;
} }
static constexpr u32 cpuRatio = 3, rspRatio = 2; static constexpr u32 cpuRatio = 3, rspRatio = 2;
regs.steps += cpuCycles; regs.steps += cpuCycles;
const auto sets = regs.steps / cpuRatio; const auto sets = regs.steps / cpuRatio;
mmio.rsp.steps += sets * rspRatio; mmio.rsp.steps += sets * rspRatio;
regs.steps -= sets * cpuRatio; regs.steps -= sets * cpuRatio;
while (mmio.rsp.steps > 0) { while (mmio.rsp.steps > 0) {
mmio.rsp.steps--; mmio.rsp.steps--;
mmio.rsp.Step(); mmio.rsp.Step();
} }
} }
void Core::Run(const float volumeL, const float volumeR) { void Core::Run(const float volumeL, const float volumeR) {
MMIO &mmio = mem->mmio; MMIO &mmio = mem->mmio;
bool broken = false; bool broken = false;
for (int field = 0; field < mmio.vi.numFields; field++) { for (int field = 0; field < mmio.vi.numFields; field++) {
u32 frameCycles = 0; u32 frameCycles = 0;
for (int i = 0; i < mmio.vi.numHalflines; i++) { for (int i = 0; i < mmio.vi.numHalflines; i++) {
mmio.vi.current = (i << 1) + field; mmio.vi.current = (i << 1) + field;
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) { if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
mmio.mi.InterruptRaise(MI::Interrupt::VI); mmio.mi.InterruptRaise(MI::Interrupt::VI);
} }
while(cycles < mem->mmio.vi.cyclesPerHalfline) { while (cycles < mem->mmio.vi.cyclesPerHalfline) {
const u32 taken = StepCPU(); const u32 taken = StepCPU();
cycles += taken; cycles += taken;
if((broken = breakpoints.contains(regs.nextPC))) if ((broken = breakpoints.contains(regs.nextPC)))
break; break;
StepRSP(taken); StepRSP(taken);
frameCycles += taken; frameCycles += taken;
Scheduler::GetInstance().Tick(taken); Scheduler::GetInstance().Tick(taken);
} }
if(broken) if (broken)
break; break;
cycles -= mmio.vi.cyclesPerHalfline; cycles -= mmio.vi.cyclesPerHalfline;
}
if (broken)
break;
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
mmio.mi.InterruptRaise(MI::Interrupt::VI);
}
mmio.ai.Step(frameCycles, volumeL, volumeR);
Scheduler::GetInstance().Tick(frameCycles);
} }
if(broken) if (broken)
break; pause = true;
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
mmio.mi.InterruptRaise(MI::Interrupt::VI);
}
mmio.ai.Step(frameCycles, volumeL, volumeR);
Scheduler::GetInstance().Tick(frameCycles);
}
if(broken)
pause = true;
} }
} // namespace n64 } // namespace n64
+24 -3
View File
@@ -4,9 +4,30 @@
#include <Disassembler.hpp> #include <Disassembler.hpp>
namespace n64 { namespace n64 {
struct alignas(32) InstructionCache {
bool valid;
u32 data[8];
u32 ptag;
private:
int GetLineIndex(u64 vaddr) { return (vaddr >> 5) & 0x1FF; }
u32 GetLineStart(u64 paddr) { return paddr & ~0x1F; }
};
struct alignas(32) DataCache {
bool valid, dirty;
u8 data[16];
u32 ptag;
int index;
private:
int GetLineIndex(u64 vaddr) { return (vaddr >> 4) & 0x1FF; }
u32 GetLineStart(u64 paddr) { return paddr & ~0xF; }
};
struct BaseCPU { struct BaseCPU {
virtual ~BaseCPU() = default; virtual ~BaseCPU() = default;
virtual u32 Step() = 0; virtual u32 Step() = 0;
virtual void Reset() = 0; virtual void Reset() = 0;
}; };
} // namespace n64 } // namespace n64
+10 -10
View File
@@ -17,19 +17,19 @@ constexpr u32 N64_CPU_FREQ = 93750000;
#endif #endif
static FORCE_INLINE constexpr u32 GetCyclesPerFrame(bool pal) { static FORCE_INLINE constexpr u32 GetCyclesPerFrame(bool pal) {
if (pal) { if (pal) {
return N64_CPU_FREQ / 50; return N64_CPU_FREQ / 50;
} else { } else {
return N64_CPU_FREQ / 60; return N64_CPU_FREQ / 60;
} }
} }
static FORCE_INLINE constexpr u32 GetVideoFrequency(bool pal) { static FORCE_INLINE constexpr u32 GetVideoFrequency(bool pal) {
if (pal) { if (pal) {
return 49'656'530; return 49'656'530;
} else { } else {
return 48'681'812; return 48'681'812;
} }
} }
#define HALF_ADDRESS(addr) ((addr) ^ 2) #define HALF_ADDRESS(addr) ((addr) ^ 2)