diff --git a/include/mgba/internal/arm/isa-inlines.h b/include/mgba/internal/arm/isa-inlines.h index 5850dab69..50d96f73a 100644 --- a/include/mgba/internal/arm/isa-inlines.h +++ b/include/mgba/internal/arm/isa-inlines.h @@ -88,7 +88,8 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution case MODE_THUMB: cpu->cpsr.t = 1; } - cpu->nextEvent = cpu->cycles; + cpu->nextEvent -= cpu->cycles; + cpu->cycles = 0; } static inline void _ARMReadCPSR(struct ARMCore* cpu) { diff --git a/src/arm/arm.c b/src/arm/arm.c index 618f34750..c8e19c9df 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -166,7 +166,7 @@ void ARMRaiseIRQ(struct ARMCore* cpu) { _ARMSetMode(cpu, MODE_ARM); cpu->spsr = cpsr; cpu->cpsr.i = 1; - cpu->cycles += currentCycles; + cpu->cycles -= currentCycles; } void ARMRaiseSWI(struct ARMCore* cpu) { @@ -186,7 +186,7 @@ void ARMRaiseSWI(struct ARMCore* cpu) { _ARMSetMode(cpu, MODE_ARM); cpu->spsr = cpsr; cpu->cpsr.i = 1; - cpu->cycles += currentCycles; + cpu->cycles -= currentCycles; } void ARMRaiseUndefined(struct ARMCore* cpu) { @@ -206,7 +206,7 @@ void ARMRaiseUndefined(struct ARMCore* cpu) { _ARMSetMode(cpu, MODE_ARM); cpu->spsr = cpsr; cpu->cpsr.i = 1; - cpu->cycles += currentCycles; + cpu->cycles -= currentCycles; } static inline void ARMStep(struct ARMCore* cpu) { @@ -265,7 +265,7 @@ static inline void ARMStep(struct ARMCore* cpu) { break; } if (!conditionMet) { - cpu->cycles += ARM_PREFETCH_CYCLES; + cpu->cycles -= ARM_PREFETCH_CYCLES; return; } } @@ -288,18 +288,18 @@ void ARMRun(struct ARMCore* cpu) { } else { ARMStep(cpu); } - if (cpu->cycles >= cpu->nextEvent) { + if (cpu->cycles <= 0) { cpu->irqh.processEvents(cpu); } } void ARMRunLoop(struct ARMCore* cpu) { if (cpu->executionMode == MODE_THUMB) { - while (cpu->cycles < cpu->nextEvent) { + while (cpu->cycles > 0) { ThumbStep(cpu); } } else { - while (cpu->cycles < cpu->nextEvent) { + while (cpu->cycles > 0) { ARMStep(cpu); } } diff --git a/src/arm/debugger/debugger.c b/src/arm/debugger/debugger.c index 55105a17d..6f61feae0 100644 --- a/src/arm/debugger/debugger.c +++ b/src/arm/debugger/debugger.c @@ -139,7 +139,9 @@ void ARMDebuggerDeinit(struct mDebuggerPlatform* platform) { static void ARMDebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { struct ARMDebugger* debugger = (struct ARMDebugger*) platform; struct ARMCore* cpu = debugger->cpu; - cpu->nextEvent = cpu->cycles; + cpu->nextEvent -= cpu->cycles; + cpu->cycles = 0; + if (reason == DEBUGGER_ENTER_BREAKPOINT) { struct ARMDebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu)); if (breakpoint && breakpoint->isSw) { diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index e9ed19a2d..a5a42ee50 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -288,7 +288,7 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) { static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \ int currentCycles = ARM_PREFETCH_CYCLES; \ BODY; \ - cpu->cycles += currentCycles; \ + cpu->cycles -= currentCycles; \ } #define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY) \ diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index 54faf6ddc..7ad598b30 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -51,7 +51,7 @@ static void _ThumbInstruction ## NAME (struct ARMCore* cpu, uint16_t opcode) { \ int currentCycles = THUMB_PREFETCH_CYCLES; \ BODY; \ - cpu->cycles += currentCycles; \ + cpu->cycles -= currentCycles; \ } #define DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(NAME, BODY) \ diff --git a/src/core/timing.c b/src/core/timing.c index be63c1029..bf3d15a10 100644 --- a/src/core/timing.c +++ b/src/core/timing.c @@ -23,9 +23,10 @@ void mTimingClear(struct mTiming* timing) { } void mTimingSchedule(struct mTiming* timing, struct mTimingEvent* event, int32_t when) { - int32_t nextEvent = when + *timing->relativeCycles; + int32_t nextEvent = when + *timing->nextEvent - *timing->relativeCycles; event->when = nextEvent + timing->masterCycles; - if (nextEvent < *timing->nextEvent) { + if (when < *timing->relativeCycles) { + *timing->relativeCycles = when; *timing->nextEvent = nextEvent; } struct mTimingEvent** previous = &timing->root; @@ -91,7 +92,7 @@ int32_t mTimingTick(struct mTiming* timing, int32_t cycles) { } int32_t mTimingCurrentTime(const struct mTiming* timing) { - return timing->masterCycles + *timing->relativeCycles; + return timing->masterCycles + *timing->nextEvent - *timing->relativeCycles; } int32_t mTimingNextEvent(struct mTiming* timing) { @@ -99,9 +100,9 @@ int32_t mTimingNextEvent(struct mTiming* timing) { if (!next) { return INT_MAX; } - return next->when - timing->masterCycles - *timing->relativeCycles; + return next->when - timing->masterCycles - *timing->nextEvent + *timing->relativeCycles; } int32_t mTimingUntil(const struct mTiming* timing, const struct mTimingEvent* event) { - return event->when - timing->masterCycles - *timing->relativeCycles; + return event->when - timing->masterCycles - *timing->nextEvent + *timing->relativeCycles; } diff --git a/src/gb/gb.c b/src/gb/gb.c index 3a812afa7..6632ca480 100644 --- a/src/gb/gb.c +++ b/src/gb/gb.c @@ -639,10 +639,10 @@ void GBUpdateIRQs(struct GB* gb) { void GBProcessEvents(struct LR35902Core* cpu) { struct GB* gb = (struct GB*) cpu->master; do { - int32_t cycles = cpu->cycles; + int32_t cycles = cpu->nextEvent - cpu->cycles; int32_t nextEvent; - cpu->cycles = 0; + cpu->cycles = INT_MAX; cpu->nextEvent = INT_MAX; nextEvent = cycles; @@ -650,9 +650,10 @@ void GBProcessEvents(struct LR35902Core* cpu) { nextEvent = mTimingTick(&gb->timing, nextEvent); } while (gb->cpuBlocked); cpu->nextEvent = nextEvent; + cpu->cycles = nextEvent; if (cpu->halted) { - cpu->cycles = cpu->nextEvent; + cpu->cycles = 0; if (!gb->memory.ie || !gb->memory.ime) { break; } @@ -660,7 +661,7 @@ void GBProcessEvents(struct LR35902Core* cpu) { if (gb->earlyExit) { break; } - } while (cpu->cycles >= cpu->nextEvent); + } while (cpu->cycles <= 0); gb->earlyExit = false; } @@ -713,7 +714,7 @@ static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cycle void GBHalt(struct LR35902Core* cpu) { struct GB* gb = (struct GB*) cpu->master; if (!(gb->memory.ie & gb->memory.io[REG_IF])) { - cpu->cycles = cpu->nextEvent; + cpu->cycles = 0; cpu->halted = true; } else if (gb->model < GB_MODEL_CGB) { mLOG(GB, STUB, "Unimplemented HALT bug"); diff --git a/src/gb/memory.c b/src/gb/memory.c index 688d43676..9f94f1671 100644 --- a/src/gb/memory.c +++ b/src/gb/memory.c @@ -476,8 +476,9 @@ void GBMemoryDMA(struct GB* gb, uint16_t base) { } mTimingDeschedule(&gb->timing, &gb->memory.dmaEvent); mTimingSchedule(&gb->timing, &gb->memory.dmaEvent, 8); - if (gb->cpu->cycles + 8 < gb->cpu->nextEvent) { - gb->cpu->nextEvent = gb->cpu->cycles + 8; + if (gb->cpu->cycles < 8) { + gb->cpu->nextEvent += 8 - gb->cpu->cycles; + gb->cpu->cycles = 8; } gb->memory.dmaSource = base; gb->memory.dmaDest = 0; diff --git a/src/gb/serialize.c b/src/gb/serialize.c index 67046a888..29beb9d79 100644 --- a/src/gb/serialize.c +++ b/src/gb/serialize.c @@ -43,7 +43,8 @@ void GBSerialize(struct GB* gb, struct GBSerializedState* state) { STORE_16LE(gb->cpu->sp, 0, &state->cpu.sp); STORE_16LE(gb->cpu->pc, 0, &state->cpu.pc); - STORE_32LE(gb->cpu->cycles, 0, &state->cpu.cycles); + int32_t cycles = gb->cpu->nextEvent - gb->cpu->cycles; + STORE_32LE(cycles, 0, &state->cpu.cycles); STORE_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent); STORE_16LE(gb->cpu->index, 0, &state->cpu.index); @@ -163,8 +164,10 @@ bool GBDeserialize(struct GB* gb, const struct GBSerializedState* state) { gb->doubleSpeed = GBSerializedCpuFlagsGetDoubleSpeed(flags); gb->audio.timingFactor = gb->doubleSpeed + 1; - LOAD_32LE(gb->cpu->cycles, 0, &state->cpu.cycles); + int32_t cycles; + LOAD_32LE(cycles, 0, &state->cpu.cycles); LOAD_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent); + gb->cpu->cycles = gb->cpu->nextEvent - cycles; gb->timing.root = NULL; uint32_t when; diff --git a/src/gba/gba.c b/src/gba/gba.c index 38fa0fc7a..87e8e6dbd 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -251,23 +251,20 @@ static void GBAProcessEvents(struct ARMCore* cpu) { } int32_t nextEvent = cpu->nextEvent; - while (cpu->cycles >= nextEvent) { + while (cpu->cycles <= 0) { + int32_t cycles = cpu->nextEvent - cpu->cycles; cpu->nextEvent = INT_MAX; - nextEvent = 0; + cpu->cycles = INT_MAX; + nextEvent = cycles; do { - int32_t cycles = cpu->cycles; - cpu->cycles = 0; -#ifndef NDEBUG - if (cycles < 0) { - mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles); - } -#endif - nextEvent = mTimingTick(&gba->timing, nextEvent + cycles); + nextEvent = mTimingTick(&gba->timing, nextEvent); } while (gba->cpuBlocked); cpu->nextEvent = nextEvent; + cpu->cycles = nextEvent; + if (cpu->halted) { - cpu->cycles = nextEvent; + cpu->cycles = 0; if (!gba->memory.io[REG_IME >> 1] || !gba->memory.io[REG_IE >> 1]) { break; } @@ -499,12 +496,13 @@ void GBATestIRQ(struct ARMCore* cpu) { struct GBA* gba = (struct GBA*) cpu->master; if (gba->memory.io[REG_IME >> 1] && gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]) { gba->springIRQ = gba->memory.io[REG_IE >> 1] & gba->memory.io[REG_IF >> 1]; - gba->cpu->nextEvent = gba->cpu->cycles; + gba->cpu->nextEvent -= gba->cpu->cycles; + gba->cpu->cycles = 0; } } void GBAHalt(struct GBA* gba) { - gba->cpu->nextEvent = gba->cpu->cycles; + gba->cpu->cycles = 0; gba->cpu->halted = 1; } @@ -516,7 +514,7 @@ void GBAStop(struct GBA* gba) { callbacks->sleep(callbacks->context); } } - gba->cpu->nextEvent = gba->cpu->cycles; + gba->cpu->cycles = 0; } void GBADebug(struct GBA* gba, uint16_t flags) { diff --git a/src/gba/memory.c b/src/gba/memory.c index 0ae984eff..e61592314 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -1613,7 +1613,7 @@ int32_t GBAMemoryStall(struct ARMCore* cpu, int32_t wait) { memory->lastPrefetchedPc = cpu->gprs[ARM_PC] + WORD_SIZE_THUMB * (loads + previousLoads - 1); // The next |loads|S waitstates disappear entirely, so long as they're all in a row - cpu->cycles -= (s - 1) * loads; + cpu->cycles += (s - 1) * loads; return wait; } diff --git a/src/gba/serialize.c b/src/gba/serialize.c index 0f1820833..41714d8b2 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -44,7 +44,9 @@ void GBASerialize(struct GBA* gba, struct GBASerializedState* state) { } STORE_32(gba->cpu->cpsr.packed, 0, &state->cpu.cpsr.packed); STORE_32(gba->cpu->spsr.packed, 0, &state->cpu.spsr.packed); - STORE_32(gba->cpu->cycles, 0, &state->cpu.cycles); + + int32_t cycles = gba->cpu->nextEvent - gba->cpu->cycles; + STORE_32(cycles, 0, &state->cpu.cycles); STORE_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent); for (i = 0; i < 6; ++i) { int j; @@ -136,8 +138,12 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { } LOAD_32(gba->cpu->cpsr.packed, 0, &state->cpu.cpsr.packed); LOAD_32(gba->cpu->spsr.packed, 0, &state->cpu.spsr.packed); - LOAD_32(gba->cpu->cycles, 0, &state->cpu.cycles); + + int32_t cycles; + LOAD_32(cycles, 0, &state->cpu.cycles); LOAD_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent); + gba->cpu->cycles = gba->cpu->nextEvent - cycles; + for (i = 0; i < 6; ++i) { int j; for (j = 0; j < 7; ++j) { diff --git a/src/lr35902/debugger/debugger.c b/src/lr35902/debugger/debugger.c index 04337f463..cc52bf65c 100644 --- a/src/lr35902/debugger/debugger.c +++ b/src/lr35902/debugger/debugger.c @@ -123,7 +123,8 @@ static void LR35902DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebug UNUSED(info); struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; struct LR35902Core* cpu = debugger->cpu; - cpu->nextEvent = cpu->cycles; + cpu->nextEvent -= cpu->cycles; + cpu->cycles = 0; if (debugger->d.p->entered) { debugger->d.p->entered(debugger->d.p, reason, info); diff --git a/src/lr35902/lr35902.c b/src/lr35902/lr35902.c index 4ae2a1e07..822bb1d59 100644 --- a/src/lr35902/lr35902.c +++ b/src/lr35902/lr35902.c @@ -102,7 +102,7 @@ static void _LR35902InstructionIRQ(struct LR35902Core* cpu) { } static void _LR35902Step(struct LR35902Core* cpu) { - ++cpu->cycles; + --cpu->cycles; enum LR35902ExecutionState state = cpu->executionState; cpu->executionState = LR35902_CORE_IDLE_0; switch (state) { @@ -137,44 +137,44 @@ static void _LR35902Step(struct LR35902Core* cpu) { } void LR35902Tick(struct LR35902Core* cpu) { - while (cpu->cycles >= cpu->nextEvent) { + while (cpu->cycles <= 0) { cpu->irqh.processEvents(cpu); } _LR35902Step(cpu); - if (cpu->cycles + 2 >= cpu->nextEvent) { - int32_t diff = cpu->nextEvent - cpu->cycles; - cpu->cycles = cpu->nextEvent; + if (cpu->cycles <= 2) { + int32_t diff = cpu->cycles; + cpu->cycles = 0; cpu->executionState += diff; cpu->irqh.processEvents(cpu); - cpu->cycles += LR35902_CORE_EXECUTE - cpu->executionState; + cpu->cycles -= LR35902_CORE_EXECUTE - cpu->executionState; } else { - cpu->cycles += 2; + cpu->cycles -= 2; } cpu->executionState = LR35902_CORE_FETCH; cpu->instruction(cpu); - ++cpu->cycles; + --cpu->cycles; } void LR35902Run(struct LR35902Core* cpu) { bool running = true; while (running || cpu->executionState != LR35902_CORE_FETCH) { - if (cpu->cycles >= cpu->nextEvent) { + if (cpu->cycles <= 0) { cpu->irqh.processEvents(cpu); break; } _LR35902Step(cpu); - if (cpu->cycles + 2 >= cpu->nextEvent) { - int32_t diff = cpu->nextEvent - cpu->cycles; - cpu->cycles = cpu->nextEvent; + if (cpu->cycles <= 2) { + int32_t diff = cpu->cycles; + cpu->cycles = 0; cpu->executionState += diff; cpu->irqh.processEvents(cpu); - cpu->cycles += LR35902_CORE_EXECUTE - cpu->executionState; + cpu->cycles -= LR35902_CORE_EXECUTE - cpu->executionState; running = false; } else { - cpu->cycles += 2; + cpu->cycles -= 2; } cpu->executionState = LR35902_CORE_FETCH; cpu->instruction(cpu); - ++cpu->cycles; + --cpu->cycles; } }