reduce branching in emulation of CPU/RSP parallelization
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <n64/core/RSP.hpp>
|
||||
#include <util.hpp>
|
||||
#include <n64/core/Mem.hpp>
|
||||
#include <n64/core/cpu/Registers.hpp>
|
||||
|
||||
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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -13,5 +13,6 @@ struct Registers {
|
||||
s64 oldPC, pc, nextPC;
|
||||
s64 hi, lo;
|
||||
bool prevDelaySlot, delaySlot;
|
||||
int steps = 0;
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user