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) {
|
void Core::Run(Window& window, float volumeL, float volumeR) {
|
||||||
MMIO& mmio = mem.mmio;
|
MMIO& mmio = mem.mmio;
|
||||||
Controller& controller = mmio.si.controller;
|
Controller& controller = mmio.si.controller;
|
||||||
int cpuSteps = 0;
|
|
||||||
for(int field = 0; field < mmio.vi.numFields; field++) {
|
for(int field = 0; field < mmio.vi.numFields; field++) {
|
||||||
int frameCycles = 0;
|
int frameCycles = 0;
|
||||||
if(!pause && romLoaded) {
|
if(!pause && romLoaded) {
|
||||||
@@ -46,14 +46,11 @@ void Core::Run(Window& window, float volumeL, float volumeR) {
|
|||||||
|
|
||||||
for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
||||||
cpu.Step(mem);
|
cpu.Step(mem);
|
||||||
cpuSteps++;
|
if(!mmio.rsp.spStatus.halt) {
|
||||||
if(mmio.rsp.spStatus.halt) {
|
cpu.regs.steps++;
|
||||||
mmio.rsp.steps = 0;
|
if(cpu.regs.steps > 2) {
|
||||||
cpuSteps = 0;
|
|
||||||
} else {
|
|
||||||
if(cpuSteps > 2) {
|
|
||||||
mmio.rsp.steps += 2;
|
mmio.rsp.steps += 2;
|
||||||
cpuSteps -= 3;
|
cpu.regs.steps -= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
while(mmio.rsp.steps > 0) {
|
while(mmio.rsp.steps > 0) {
|
||||||
|
|||||||
@@ -53,13 +53,13 @@ void Cpu::Step(Mem& mem) {
|
|||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
regs.delaySlot = false;
|
regs.delaySlot = false;
|
||||||
|
|
||||||
u32 instruction = mem.Read32(regs, regs.pc, regs.pc);
|
|
||||||
|
|
||||||
if(ShouldServiceInterrupt(regs)) {
|
if(ShouldServiceInterrupt(regs)) {
|
||||||
FireException(regs, ExceptionCode::Interrupt, 0, regs.pc);
|
FireException(regs, ExceptionCode::Interrupt, 0, regs.pc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 instruction = mem.Read32(regs, regs.pc, regs.pc);
|
||||||
|
|
||||||
regs.oldPC = regs.pc;
|
regs.oldPC = regs.pc;
|
||||||
regs.pc = regs.nextPC;
|
regs.pc = regs.nextPC;
|
||||||
regs.nextPC += 4;
|
regs.nextPC += 4;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <n64/core/RSP.hpp>
|
#include <n64/core/RSP.hpp>
|
||||||
#include <util.hpp>
|
#include <util.hpp>
|
||||||
#include <n64/core/Mem.hpp>
|
#include <n64/core/Mem.hpp>
|
||||||
|
#include <n64/core/cpu/Registers.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
RSP::RSP() {
|
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) {
|
void RSP::Write(Mem& mem, Registers& regs, u32 addr, u32 value) {
|
||||||
MI& mi = mem.mmio.mi;
|
MI& mi = mem.mmio.mi;
|
||||||
switch (addr) {
|
switch (addr) {
|
||||||
|
|||||||
@@ -194,31 +194,6 @@ struct RSP {
|
|||||||
return value;
|
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) {
|
inline u32 ReadWord(u32 addr) {
|
||||||
addr &= 0xfff;
|
addr &= 0xfff;
|
||||||
return GET_RSP_WORD(addr);
|
return GET_RSP_WORD(addr);
|
||||||
@@ -400,6 +375,8 @@ struct RSP {
|
|||||||
rsp.lastSuccessfulDRAMAddr.address = dram_address;
|
rsp.lastSuccessfulDRAMAddr.address = dram_address;
|
||||||
rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20);
|
rsp.spDMALen.raw = 0xFF8 | (rsp.spDMALen.skip << 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteStatus(MI& mi, Registers& regs, u32 value);
|
||||||
private:
|
private:
|
||||||
inline void branch(u16 address, bool cond) {
|
inline void branch(u16 address, bool cond) {
|
||||||
if(cond) {
|
if(cond) {
|
||||||
|
|||||||
@@ -13,5 +13,6 @@ struct Registers {
|
|||||||
s64 oldPC, pc, nextPC;
|
s64 oldPC, pc, nextPC;
|
||||||
s64 hi, lo;
|
s64 hi, lo;
|
||||||
bool prevDelaySlot, delaySlot;
|
bool prevDelaySlot, delaySlot;
|
||||||
|
int steps = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user