Core: Revise clock timing (WIP)

This commit is contained in:
Vicki Pfau 2018-08-27 20:52:12 -07:00
parent e45519075a
commit b2e2965273
14 changed files with 72 additions and 58 deletions

View File

@ -88,7 +88,8 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution
case MODE_THUMB: case MODE_THUMB:
cpu->cpsr.t = 1; cpu->cpsr.t = 1;
} }
cpu->nextEvent = cpu->cycles; cpu->nextEvent -= cpu->cycles;
cpu->cycles = 0;
} }
static inline void _ARMReadCPSR(struct ARMCore* cpu) { static inline void _ARMReadCPSR(struct ARMCore* cpu) {

View File

@ -166,7 +166,7 @@ void ARMRaiseIRQ(struct ARMCore* cpu) {
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
cpu->cpsr.i = 1; cpu->cpsr.i = 1;
cpu->cycles += currentCycles; cpu->cycles -= currentCycles;
} }
void ARMRaiseSWI(struct ARMCore* cpu) { void ARMRaiseSWI(struct ARMCore* cpu) {
@ -186,7 +186,7 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
cpu->cpsr.i = 1; cpu->cpsr.i = 1;
cpu->cycles += currentCycles; cpu->cycles -= currentCycles;
} }
void ARMRaiseUndefined(struct ARMCore* cpu) { void ARMRaiseUndefined(struct ARMCore* cpu) {
@ -206,7 +206,7 @@ void ARMRaiseUndefined(struct ARMCore* cpu) {
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
cpu->cpsr.i = 1; cpu->cpsr.i = 1;
cpu->cycles += currentCycles; cpu->cycles -= currentCycles;
} }
static inline void ARMStep(struct ARMCore* cpu) { static inline void ARMStep(struct ARMCore* cpu) {
@ -265,7 +265,7 @@ static inline void ARMStep(struct ARMCore* cpu) {
break; break;
} }
if (!conditionMet) { if (!conditionMet) {
cpu->cycles += ARM_PREFETCH_CYCLES; cpu->cycles -= ARM_PREFETCH_CYCLES;
return; return;
} }
} }
@ -288,18 +288,18 @@ void ARMRun(struct ARMCore* cpu) {
} else { } else {
ARMStep(cpu); ARMStep(cpu);
} }
if (cpu->cycles >= cpu->nextEvent) { if (cpu->cycles <= 0) {
cpu->irqh.processEvents(cpu); cpu->irqh.processEvents(cpu);
} }
} }
void ARMRunLoop(struct ARMCore* cpu) { void ARMRunLoop(struct ARMCore* cpu) {
if (cpu->executionMode == MODE_THUMB) { if (cpu->executionMode == MODE_THUMB) {
while (cpu->cycles < cpu->nextEvent) { while (cpu->cycles > 0) {
ThumbStep(cpu); ThumbStep(cpu);
} }
} else { } else {
while (cpu->cycles < cpu->nextEvent) { while (cpu->cycles > 0) {
ARMStep(cpu); ARMStep(cpu);
} }
} }

View File

@ -139,7 +139,9 @@ void ARMDebuggerDeinit(struct mDebuggerPlatform* platform) {
static void ARMDebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) { static void ARMDebuggerEnter(struct mDebuggerPlatform* platform, enum mDebuggerEntryReason reason, struct mDebuggerEntryInfo* info) {
struct ARMDebugger* debugger = (struct ARMDebugger*) platform; struct ARMDebugger* debugger = (struct ARMDebugger*) platform;
struct ARMCore* cpu = debugger->cpu; struct ARMCore* cpu = debugger->cpu;
cpu->nextEvent = cpu->cycles; cpu->nextEvent -= cpu->cycles;
cpu->cycles = 0;
if (reason == DEBUGGER_ENTER_BREAKPOINT) { if (reason == DEBUGGER_ENTER_BREAKPOINT) {
struct ARMDebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu)); struct ARMDebugBreakpoint* breakpoint = _lookupBreakpoint(&debugger->swBreakpoints, _ARMPCAddress(cpu));
if (breakpoint && breakpoint->isSw) { if (breakpoint && breakpoint->isSw) {

View File

@ -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) { \ static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \
int currentCycles = ARM_PREFETCH_CYCLES; \ int currentCycles = ARM_PREFETCH_CYCLES; \
BODY; \ BODY; \
cpu->cycles += currentCycles; \ cpu->cycles -= currentCycles; \
} }
#define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY) \ #define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY) \

View File

@ -51,7 +51,7 @@
static void _ThumbInstruction ## NAME (struct ARMCore* cpu, uint16_t opcode) { \ static void _ThumbInstruction ## NAME (struct ARMCore* cpu, uint16_t opcode) { \
int currentCycles = THUMB_PREFETCH_CYCLES; \ int currentCycles = THUMB_PREFETCH_CYCLES; \
BODY; \ BODY; \
cpu->cycles += currentCycles; \ cpu->cycles -= currentCycles; \
} }
#define DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(NAME, BODY) \ #define DEFINE_IMMEDIATE_5_INSTRUCTION_THUMB(NAME, BODY) \

View File

@ -23,9 +23,10 @@ void mTimingClear(struct mTiming* timing) {
} }
void mTimingSchedule(struct mTiming* timing, struct mTimingEvent* event, int32_t when) { 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; event->when = nextEvent + timing->masterCycles;
if (nextEvent < *timing->nextEvent) { if (when < *timing->relativeCycles) {
*timing->relativeCycles = when;
*timing->nextEvent = nextEvent; *timing->nextEvent = nextEvent;
} }
struct mTimingEvent** previous = &timing->root; 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) { 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) { int32_t mTimingNextEvent(struct mTiming* timing) {
@ -99,9 +100,9 @@ int32_t mTimingNextEvent(struct mTiming* timing) {
if (!next) { if (!next) {
return INT_MAX; 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) { 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;
} }

View File

@ -639,10 +639,10 @@ void GBUpdateIRQs(struct GB* gb) {
void GBProcessEvents(struct LR35902Core* cpu) { void GBProcessEvents(struct LR35902Core* cpu) {
struct GB* gb = (struct GB*) cpu->master; struct GB* gb = (struct GB*) cpu->master;
do { do {
int32_t cycles = cpu->cycles; int32_t cycles = cpu->nextEvent - cpu->cycles;
int32_t nextEvent; int32_t nextEvent;
cpu->cycles = 0; cpu->cycles = INT_MAX;
cpu->nextEvent = INT_MAX; cpu->nextEvent = INT_MAX;
nextEvent = cycles; nextEvent = cycles;
@ -650,9 +650,10 @@ void GBProcessEvents(struct LR35902Core* cpu) {
nextEvent = mTimingTick(&gb->timing, nextEvent); nextEvent = mTimingTick(&gb->timing, nextEvent);
} while (gb->cpuBlocked); } while (gb->cpuBlocked);
cpu->nextEvent = nextEvent; cpu->nextEvent = nextEvent;
cpu->cycles = nextEvent;
if (cpu->halted) { if (cpu->halted) {
cpu->cycles = cpu->nextEvent; cpu->cycles = 0;
if (!gb->memory.ie || !gb->memory.ime) { if (!gb->memory.ie || !gb->memory.ime) {
break; break;
} }
@ -660,7 +661,7 @@ void GBProcessEvents(struct LR35902Core* cpu) {
if (gb->earlyExit) { if (gb->earlyExit) {
break; break;
} }
} while (cpu->cycles >= cpu->nextEvent); } while (cpu->cycles <= 0);
gb->earlyExit = false; gb->earlyExit = false;
} }
@ -713,7 +714,7 @@ static void _enableInterrupts(struct mTiming* timing, void* user, uint32_t cycle
void GBHalt(struct LR35902Core* cpu) { void GBHalt(struct LR35902Core* cpu) {
struct GB* gb = (struct GB*) cpu->master; struct GB* gb = (struct GB*) cpu->master;
if (!(gb->memory.ie & gb->memory.io[REG_IF])) { if (!(gb->memory.ie & gb->memory.io[REG_IF])) {
cpu->cycles = cpu->nextEvent; cpu->cycles = 0;
cpu->halted = true; cpu->halted = true;
} else if (gb->model < GB_MODEL_CGB) { } else if (gb->model < GB_MODEL_CGB) {
mLOG(GB, STUB, "Unimplemented HALT bug"); mLOG(GB, STUB, "Unimplemented HALT bug");

View File

@ -476,8 +476,9 @@ void GBMemoryDMA(struct GB* gb, uint16_t base) {
} }
mTimingDeschedule(&gb->timing, &gb->memory.dmaEvent); mTimingDeschedule(&gb->timing, &gb->memory.dmaEvent);
mTimingSchedule(&gb->timing, &gb->memory.dmaEvent, 8); mTimingSchedule(&gb->timing, &gb->memory.dmaEvent, 8);
if (gb->cpu->cycles + 8 < gb->cpu->nextEvent) { if (gb->cpu->cycles < 8) {
gb->cpu->nextEvent = gb->cpu->cycles + 8; gb->cpu->nextEvent += 8 - gb->cpu->cycles;
gb->cpu->cycles = 8;
} }
gb->memory.dmaSource = base; gb->memory.dmaSource = base;
gb->memory.dmaDest = 0; gb->memory.dmaDest = 0;

View File

@ -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->sp, 0, &state->cpu.sp);
STORE_16LE(gb->cpu->pc, 0, &state->cpu.pc); 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_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent);
STORE_16LE(gb->cpu->index, 0, &state->cpu.index); 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->doubleSpeed = GBSerializedCpuFlagsGetDoubleSpeed(flags);
gb->audio.timingFactor = gb->doubleSpeed + 1; 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); LOAD_32LE(gb->cpu->nextEvent, 0, &state->cpu.nextEvent);
gb->cpu->cycles = gb->cpu->nextEvent - cycles;
gb->timing.root = NULL; gb->timing.root = NULL;
uint32_t when; uint32_t when;

View File

@ -251,23 +251,20 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
} }
int32_t nextEvent = cpu->nextEvent; int32_t nextEvent = cpu->nextEvent;
while (cpu->cycles >= nextEvent) { while (cpu->cycles <= 0) {
int32_t cycles = cpu->nextEvent - cpu->cycles;
cpu->nextEvent = INT_MAX; cpu->nextEvent = INT_MAX;
nextEvent = 0; cpu->cycles = INT_MAX;
nextEvent = cycles;
do { do {
int32_t cycles = cpu->cycles; nextEvent = mTimingTick(&gba->timing, nextEvent);
cpu->cycles = 0;
#ifndef NDEBUG
if (cycles < 0) {
mLOG(GBA, FATAL, "Negative cycles passed: %i", cycles);
}
#endif
nextEvent = mTimingTick(&gba->timing, nextEvent + cycles);
} while (gba->cpuBlocked); } while (gba->cpuBlocked);
cpu->nextEvent = nextEvent; cpu->nextEvent = nextEvent;
cpu->cycles = nextEvent;
if (cpu->halted) { if (cpu->halted) {
cpu->cycles = nextEvent; cpu->cycles = 0;
if (!gba->memory.io[REG_IME >> 1] || !gba->memory.io[REG_IE >> 1]) { if (!gba->memory.io[REG_IME >> 1] || !gba->memory.io[REG_IE >> 1]) {
break; break;
} }
@ -499,12 +496,13 @@ void GBATestIRQ(struct ARMCore* cpu) {
struct GBA* gba = (struct GBA*) cpu->master; 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]) { 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->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) { void GBAHalt(struct GBA* gba) {
gba->cpu->nextEvent = gba->cpu->cycles; gba->cpu->cycles = 0;
gba->cpu->halted = 1; gba->cpu->halted = 1;
} }
@ -516,7 +514,7 @@ void GBAStop(struct GBA* gba) {
callbacks->sleep(callbacks->context); callbacks->sleep(callbacks->context);
} }
} }
gba->cpu->nextEvent = gba->cpu->cycles; gba->cpu->cycles = 0;
} }
void GBADebug(struct GBA* gba, uint16_t flags) { void GBADebug(struct GBA* gba, uint16_t flags) {

View File

@ -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); 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 // 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; return wait;
} }

View File

@ -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->cpsr.packed, 0, &state->cpu.cpsr.packed);
STORE_32(gba->cpu->spsr.packed, 0, &state->cpu.spsr.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); STORE_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent);
for (i = 0; i < 6; ++i) { for (i = 0; i < 6; ++i) {
int j; 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->cpsr.packed, 0, &state->cpu.cpsr.packed);
LOAD_32(gba->cpu->spsr.packed, 0, &state->cpu.spsr.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); LOAD_32(gba->cpu->nextEvent, 0, &state->cpu.nextEvent);
gba->cpu->cycles = gba->cpu->nextEvent - cycles;
for (i = 0; i < 6; ++i) { for (i = 0; i < 6; ++i) {
int j; int j;
for (j = 0; j < 7; ++j) { for (j = 0; j < 7; ++j) {

View File

@ -123,7 +123,8 @@ static void LR35902DebuggerEnter(struct mDebuggerPlatform* platform, enum mDebug
UNUSED(info); UNUSED(info);
struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform; struct LR35902Debugger* debugger = (struct LR35902Debugger*) platform;
struct LR35902Core* cpu = debugger->cpu; struct LR35902Core* cpu = debugger->cpu;
cpu->nextEvent = cpu->cycles; cpu->nextEvent -= cpu->cycles;
cpu->cycles = 0;
if (debugger->d.p->entered) { if (debugger->d.p->entered) {
debugger->d.p->entered(debugger->d.p, reason, info); debugger->d.p->entered(debugger->d.p, reason, info);

View File

@ -102,7 +102,7 @@ static void _LR35902InstructionIRQ(struct LR35902Core* cpu) {
} }
static void _LR35902Step(struct LR35902Core* cpu) { static void _LR35902Step(struct LR35902Core* cpu) {
++cpu->cycles; --cpu->cycles;
enum LR35902ExecutionState state = cpu->executionState; enum LR35902ExecutionState state = cpu->executionState;
cpu->executionState = LR35902_CORE_IDLE_0; cpu->executionState = LR35902_CORE_IDLE_0;
switch (state) { switch (state) {
@ -137,44 +137,44 @@ static void _LR35902Step(struct LR35902Core* cpu) {
} }
void LR35902Tick(struct LR35902Core* cpu) { void LR35902Tick(struct LR35902Core* cpu) {
while (cpu->cycles >= cpu->nextEvent) { while (cpu->cycles <= 0) {
cpu->irqh.processEvents(cpu); cpu->irqh.processEvents(cpu);
} }
_LR35902Step(cpu); _LR35902Step(cpu);
if (cpu->cycles + 2 >= cpu->nextEvent) { if (cpu->cycles <= 2) {
int32_t diff = cpu->nextEvent - cpu->cycles; int32_t diff = cpu->cycles;
cpu->cycles = cpu->nextEvent; cpu->cycles = 0;
cpu->executionState += diff; cpu->executionState += diff;
cpu->irqh.processEvents(cpu); cpu->irqh.processEvents(cpu);
cpu->cycles += LR35902_CORE_EXECUTE - cpu->executionState; cpu->cycles -= LR35902_CORE_EXECUTE - cpu->executionState;
} else { } else {
cpu->cycles += 2; cpu->cycles -= 2;
} }
cpu->executionState = LR35902_CORE_FETCH; cpu->executionState = LR35902_CORE_FETCH;
cpu->instruction(cpu); cpu->instruction(cpu);
++cpu->cycles; --cpu->cycles;
} }
void LR35902Run(struct LR35902Core* cpu) { void LR35902Run(struct LR35902Core* cpu) {
bool running = true; bool running = true;
while (running || cpu->executionState != LR35902_CORE_FETCH) { while (running || cpu->executionState != LR35902_CORE_FETCH) {
if (cpu->cycles >= cpu->nextEvent) { if (cpu->cycles <= 0) {
cpu->irqh.processEvents(cpu); cpu->irqh.processEvents(cpu);
break; break;
} }
_LR35902Step(cpu); _LR35902Step(cpu);
if (cpu->cycles + 2 >= cpu->nextEvent) { if (cpu->cycles <= 2) {
int32_t diff = cpu->nextEvent - cpu->cycles; int32_t diff = cpu->cycles;
cpu->cycles = cpu->nextEvent; cpu->cycles = 0;
cpu->executionState += diff; cpu->executionState += diff;
cpu->irqh.processEvents(cpu); cpu->irqh.processEvents(cpu);
cpu->cycles += LR35902_CORE_EXECUTE - cpu->executionState; cpu->cycles -= LR35902_CORE_EXECUTE - cpu->executionState;
running = false; running = false;
} else { } else {
cpu->cycles += 2; cpu->cycles -= 2;
} }
cpu->executionState = LR35902_CORE_FETCH; cpu->executionState = LR35902_CORE_FETCH;
cpu->instruction(cpu); cpu->instruction(cpu);
++cpu->cycles; --cpu->cycles;
} }
} }