HUGE performance boost thanks to advice from @fleroviux ❤️
This commit is contained in:
@@ -47,29 +47,12 @@ void Core::Run(Window& window, float volumeL, float volumeR) {
|
|||||||
InterruptRaise(mmio.mi, regs, Interrupt::VI);
|
InterruptRaise(mmio.mi, regs, Interrupt::VI);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;cycles <= mmio.vi.cyclesPerHalfline; cycles++, frameCycles++) {
|
int cpuCount = CpuStep(*this);
|
||||||
int cpuCount = CpuStep(*this);
|
frameCycles += cpuCount;
|
||||||
int oldCpuCount = cpuCount;
|
|
||||||
while(cpuCount--) {
|
|
||||||
if (!mmio.rsp.spStatus.halt) {
|
|
||||||
regs.steps++;
|
|
||||||
if (regs.steps > 2) {
|
|
||||||
mmio.rsp.steps += 2;
|
|
||||||
regs.steps -= 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (mmio.rsp.steps > 0) {
|
mmio.rsp.Run(cpuCount, regs, mem);
|
||||||
mmio.rsp.steps--;
|
mmio.ai.Step(mem, regs, cpuCount, volumeL, volumeR);
|
||||||
mmio.rsp.Step(regs, mem);
|
scheduler.tick(cpuCount, mem, regs);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mmio.ai.Step(mem, regs, oldCpuCount, volumeL, volumeR);
|
|
||||||
scheduler.tick(1, mem, regs);
|
|
||||||
}
|
|
||||||
|
|
||||||
cycles -= mmio.vi.cyclesPerHalfline;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
|
if ((mmio.vi.current & 0x3FE) == mmio.vi.intr) {
|
||||||
|
|||||||
@@ -43,14 +43,15 @@ struct Core {
|
|||||||
|
|
||||||
static int CpuStep(Core& core) {
|
static int CpuStep(Core& core) {
|
||||||
switch(core.cpuType) {
|
switch(core.cpuType) {
|
||||||
case CpuType::Dynarec: return core.cpuDynarec->Step(core.mem);
|
case CpuType::Dynarec:
|
||||||
case CpuType::Interpreter: core.cpuInterp->Step(core.mem); return 1;
|
return core.cpuDynarec->Step(core.mem);
|
||||||
|
case CpuType::Interpreter:
|
||||||
|
return core.cpuInterp->Run(core.mem);
|
||||||
case CpuType::NONE: return 0;
|
case CpuType::NONE: return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 breakpoint = 0;
|
u32 breakpoint = 0;
|
||||||
int cycles = 0;
|
|
||||||
|
|
||||||
bool pause = true;
|
bool pause = true;
|
||||||
bool isPAL = false;
|
bool isPAL = false;
|
||||||
|
|||||||
@@ -21,30 +21,36 @@ inline void CheckCompareInterrupt(MI& mi, Registers& regs) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interpreter::Step(Mem& mem) {
|
int Interpreter::Run(Mem& mem) {
|
||||||
CheckCompareInterrupt(mem.mmio.mi, regs);
|
MMIO& mmio = mem.mmio;
|
||||||
|
int count = 0;
|
||||||
|
for(;count <= mmio.vi.cyclesPerHalfline; count++) {
|
||||||
|
CheckCompareInterrupt(mem.mmio.mi, regs);
|
||||||
|
|
||||||
regs.prevDelaySlot = regs.delaySlot;
|
regs.prevDelaySlot = regs.delaySlot;
|
||||||
regs.delaySlot = false;
|
regs.delaySlot = false;
|
||||||
|
|
||||||
u32 paddr = 0;
|
u32 paddr = 0;
|
||||||
if(!MapVAddr(regs, LOAD, regs.pc, paddr)) {
|
if(!MapVAddr(regs, LOAD, regs.pc, paddr)) {
|
||||||
HandleTLBException(regs, regs.pc);
|
HandleTLBException(regs, regs.pc);
|
||||||
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
FireException(regs, GetTLBExceptionCode(regs.cop0.tlbError, LOAD), 0, false);
|
||||||
return;
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 instruction = mem.Read32(regs, paddr);
|
||||||
|
|
||||||
|
if(ShouldServiceInterrupt(regs)) {
|
||||||
|
FireException(regs, ExceptionCode::Interrupt, 0, false);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs.oldPC = regs.pc;
|
||||||
|
regs.pc = regs.nextPC;
|
||||||
|
regs.nextPC += 4;
|
||||||
|
|
||||||
|
Exec(mem, instruction);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 instruction = mem.Read32(regs, paddr);
|
return count;
|
||||||
|
|
||||||
if(ShouldServiceInterrupt(regs)) {
|
|
||||||
FireException(regs, ExceptionCode::Interrupt, 0, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
regs.oldPC = regs.pc;
|
|
||||||
regs.pc = regs.nextPC;
|
|
||||||
regs.nextPC += 4;
|
|
||||||
|
|
||||||
Exec(mem, instruction);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ namespace n64 {
|
|||||||
struct Interpreter {
|
struct Interpreter {
|
||||||
Interpreter() = default;
|
Interpreter() = default;
|
||||||
~Interpreter() = default;
|
~Interpreter() = default;
|
||||||
void Step(Mem&);
|
int Run(Mem&);
|
||||||
void Reset() {
|
void Reset() {
|
||||||
regs.Reset();
|
regs.Reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,16 +66,28 @@ inline void logRSP(const RSP& rsp, const u32 instr) {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void RSP::Step(Registers& regs, Mem& mem) {
|
void RSP::Run(int cpuCount, Registers& regs, Mem& mem) {
|
||||||
gpr[0] = 0;
|
while(cpuCount--) {
|
||||||
u32 instr = Util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
if (!spStatus.halt) {
|
||||||
oldPC = pc & 0xFFC;
|
regs.steps++;
|
||||||
pc = nextPC & 0xFFC;
|
if (regs.steps > 2) {
|
||||||
nextPC += 4;
|
steps += 2;
|
||||||
|
regs.steps -= 3;
|
||||||
|
}
|
||||||
|
|
||||||
Exec(regs, mem, instr);
|
while (steps > 0) {
|
||||||
|
steps--;
|
||||||
|
gpr[0] = 0;
|
||||||
|
u32 instr = Util::ReadAccess<u32>(imem, pc & IMEM_DSIZE);
|
||||||
|
oldPC = pc & 0xFFC;
|
||||||
|
pc = nextPC & 0xFFC;
|
||||||
|
nextPC += 4;
|
||||||
|
|
||||||
//logRSP(*this, instr);
|
Exec(regs, mem, instr);
|
||||||
|
//logRSP(*this, instr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto RSP::Read(u32 addr) -> u32{
|
auto RSP::Read(u32 addr) -> u32{
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ struct Registers;
|
|||||||
struct RSP {
|
struct RSP {
|
||||||
RSP();
|
RSP();
|
||||||
void Reset();
|
void Reset();
|
||||||
void Step(Registers& regs, Mem& mem);
|
void Run(int, Registers& regs, Mem& mem);
|
||||||
auto Read(u32 addr) -> u32;
|
auto Read(u32 addr) -> u32;
|
||||||
void Write(Mem& mem, Registers& regs, u32 addr, u32 value);
|
void Write(Mem& mem, Registers& regs, u32 addr, u32 value);
|
||||||
void Exec(Registers& regs, Mem& mem, u32 instr);
|
void Exec(Registers& regs, Mem& mem, u32 instr);
|
||||||
|
|||||||
Reference in New Issue
Block a user