From 23bdd74f8a5328b54734eb027cdd8ad64c96c79f Mon Sep 17 00:00:00 2001 From: CocoSimone Date: Mon, 12 Dec 2022 02:47:16 +0100 Subject: [PATCH] reduce branching in emulation of CPU/RSP parallelization --- src/n64/Core.cpp | 13 +++++-------- src/n64/core/Cpu.cpp | 4 ++-- src/n64/core/RSP.cpp | 27 +++++++++++++++++++++++++++ src/n64/core/RSP.hpp | 27 ++------------------------- src/n64/core/cpu/Registers.hpp | 1 + 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/src/n64/Core.cpp b/src/n64/Core.cpp index a88949dc..eaeeb1a9 100644 --- a/src/n64/Core.cpp +++ b/src/n64/Core.cpp @@ -33,7 +33,7 @@ CartInfo Core::LoadROM(const std::string& rom_) { void Core::Run(Window& window, float volumeL, float volumeR) { MMIO& mmio = mem.mmio; Controller& controller = mmio.si.controller; - int cpuSteps = 0; + for(int field = 0; field < mmio.vi.numFields; field++) { int frameCycles = 0; if(!pause && romLoaded) { @@ -46,14 +46,11 @@ void Core::Run(Window& window, float volumeL, float volumeR) { for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) { cpu.Step(mem); - cpuSteps++; - if(mmio.rsp.spStatus.halt) { - mmio.rsp.steps = 0; - cpuSteps = 0; - } else { - if(cpuSteps > 2) { + if(!mmio.rsp.spStatus.halt) { + cpu.regs.steps++; + if(cpu.regs.steps > 2) { mmio.rsp.steps += 2; - cpuSteps -= 3; + cpu.regs.steps -= 3; } while(mmio.rsp.steps > 0) { diff --git a/src/n64/core/Cpu.cpp b/src/n64/core/Cpu.cpp index 8aebfc7f..c59ecf37 100644 --- a/src/n64/core/Cpu.cpp +++ b/src/n64/core/Cpu.cpp @@ -53,13 +53,13 @@ void Cpu::Step(Mem& mem) { regs.prevDelaySlot = regs.delaySlot; regs.delaySlot = false; - u32 instruction = mem.Read32(regs, regs.pc, regs.pc); - if(ShouldServiceInterrupt(regs)) { FireException(regs, ExceptionCode::Interrupt, 0, regs.pc); return; } + u32 instruction = mem.Read32(regs, regs.pc, regs.pc); + regs.oldPC = regs.pc; regs.pc = regs.nextPC; regs.nextPC += 4; diff --git a/src/n64/core/RSP.cpp b/src/n64/core/RSP.cpp index 01426d35..255fd933 100644 --- a/src/n64/core/RSP.cpp +++ b/src/n64/core/RSP.cpp @@ -1,6 +1,7 @@ #include #include #include +#include namespace n64 { RSP::RSP() { @@ -90,6 +91,32 @@ auto RSP::Read(u32 addr) -> u32{ } } +void RSP::WriteStatus(MI& mi, Registers& regs, u32 value) { + auto write = SPStatusWrite{.raw = value}; + if(write.clearHalt && !write.setHalt) { + spStatus.halt = false; + } + if(write.setHalt && !write.clearHalt) { + regs.steps = 0; + spStatus.halt = true; + } + if(write.clearBroke) spStatus.broke = false; + if(write.clearIntr && !write.setIntr) + InterruptLower(mi, regs, Interrupt::SP); + if(write.setIntr && !write.clearIntr) + InterruptRaise(mi, regs, Interrupt::SP); + CLEAR_SET(spStatus.singleStep, write.clearSstep, write.setSstep); + CLEAR_SET(spStatus.interruptOnBreak, write.clearIntrOnBreak, write.setIntrOnBreak); + CLEAR_SET(spStatus.signal0, write.clearSignal0, write.setSignal0); + CLEAR_SET(spStatus.signal1, write.clearSignal1, write.setSignal1); + CLEAR_SET(spStatus.signal2, write.clearSignal2, write.setSignal2); + CLEAR_SET(spStatus.signal3, write.clearSignal3, write.setSignal3); + CLEAR_SET(spStatus.signal4, write.clearSignal4, write.setSignal4); + CLEAR_SET(spStatus.signal5, write.clearSignal5, write.setSignal5); + CLEAR_SET(spStatus.signal6, write.clearSignal6, write.setSignal6); + CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7); +} + void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) { MI& mi = mem.mmio.mi; switch (addr) { diff --git a/src/n64/core/RSP.hpp b/src/n64/core/RSP.hpp index 37321f2a..a410c8a8 100644 --- a/src/n64/core/RSP.hpp +++ b/src/n64/core/RSP.hpp @@ -194,31 +194,6 @@ struct RSP { return value; } - inline void WriteStatus(MI& mi, Registers& regs, u32 value) { - auto write = SPStatusWrite{.raw = value}; - if(write.clearHalt && !write.setHalt) { - spStatus.halt = false; - } - if(write.setHalt && !write.clearHalt) { - spStatus.halt = true; - } - if(write.clearBroke) spStatus.broke = false; - if(write.clearIntr && !write.setIntr) - InterruptLower(mi, regs, Interrupt::SP); - if(write.setIntr && !write.clearIntr) - InterruptRaise(mi, regs, Interrupt::SP); - CLEAR_SET(spStatus.singleStep, write.clearSstep, write.setSstep); - CLEAR_SET(spStatus.interruptOnBreak, write.clearIntrOnBreak, write.setIntrOnBreak); - CLEAR_SET(spStatus.signal0, write.clearSignal0, write.setSignal0); - CLEAR_SET(spStatus.signal1, write.clearSignal1, write.setSignal1); - CLEAR_SET(spStatus.signal2, write.clearSignal2, write.setSignal2); - CLEAR_SET(spStatus.signal3, write.clearSignal3, write.setSignal3); - CLEAR_SET(spStatus.signal4, write.clearSignal4, write.setSignal4); - CLEAR_SET(spStatus.signal5, write.clearSignal5, write.setSignal5); - CLEAR_SET(spStatus.signal6, write.clearSignal6, write.setSignal6); - CLEAR_SET(spStatus.signal7, write.clearSignal7, write.setSignal7); - } - inline u32 ReadWord(u32 addr) { addr &= 0xfff; return GET_RSP_WORD(addr); @@ -400,6 +375,8 @@ struct RSP { rsp.lastSuccessfulDRAMAddr.address = dram_address; rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20); } + + void WriteStatus(MI& mi, Registers& regs, u32 value); private: inline void branch(u16 address, bool cond) { if(cond) { diff --git a/src/n64/core/cpu/Registers.hpp b/src/n64/core/cpu/Registers.hpp index d427181e..a2a1cd8c 100644 --- a/src/n64/core/cpu/Registers.hpp +++ b/src/n64/core/cpu/Registers.hpp @@ -13,5 +13,6 @@ struct Registers { s64 oldPC, pc, nextPC; s64 hi, lo; bool prevDelaySlot, delaySlot; + int steps = 0; }; }