all repos — mgba @ 334963511b513bcfc64d2b506337fea5774a18d7

mGBA Game Boy Advance Emulator

LR35902: Optimize core loop to always run one M-cycle at a time
Jeffrey Pfau jeffrey@endrift.com
Sat, 28 May 2016 01:44:05 -0700
commit

334963511b513bcfc64d2b506337fea5774a18d7

parent

d242638e28fe899406068e11681b002256708d46

1 files changed, 23 insertions(+), 9 deletions(-)

jump to
M src/lr35902/lr35902.csrc/lr35902/lr35902.c

@@ -104,8 +104,7 @@

static void _LR35902Step(struct LR35902Core* cpu) { ++cpu->cycles; enum LR35902ExecutionState state = cpu->executionState; - ++cpu->executionState; - cpu->executionState &= 3; + cpu->executionState = LR35902_CORE_IDLE_0; switch (state) { case LR35902_CORE_FETCH: if (cpu->irqPending) {

@@ -118,9 +117,6 @@ }

cpu->bus = cpu->memory.cpuLoad8(cpu, cpu->pc); cpu->instruction = _lr35902InstructionTable[cpu->bus]; ++cpu->pc; - break; - case LR35902_CORE_EXECUTE: - cpu->instruction(cpu); break; case LR35902_CORE_MEMORY_LOAD: cpu->bus = cpu->memory.load8(cpu, cpu->index);

@@ -142,6 +138,17 @@ }

void LR35902Tick(struct LR35902Core* cpu) { _LR35902Step(cpu); + if (cpu->cycles + 2 >= cpu->nextEvent) { + int32_t diff = cpu->nextEvent - cpu->cycles; + cpu->cycles = cpu->nextEvent; + cpu->irqh.processEvents(cpu); + cpu->cycles += 2 - diff; + } else { + cpu->cycles += 2; + } + cpu->executionState = LR35902_CORE_FETCH; + cpu->instruction(cpu); + ++cpu->cycles; if (cpu->cycles >= cpu->nextEvent) { cpu->irqh.processEvents(cpu); }

@@ -150,12 +157,19 @@

void LR35902Run(struct LR35902Core* cpu) { while (true) { _LR35902Step(cpu); + if (cpu->cycles + 2 >= cpu->nextEvent) { + int32_t diff = cpu->nextEvent - cpu->cycles; + cpu->cycles = cpu->nextEvent; + cpu->irqh.processEvents(cpu); + cpu->cycles += 2 - diff; + } else { + cpu->cycles += 2; + } + cpu->executionState = LR35902_CORE_FETCH; + cpu->instruction(cpu); + ++cpu->cycles; if (cpu->cycles >= cpu->nextEvent) { break; - } else if (cpu->executionState < LR35902_CORE_EXECUTE) { - // Silly hack: keep us from calling step if we know the next step is a no-op - ++cpu->cycles; - ++cpu->executionState; } } cpu->irqh.processEvents(cpu);