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:
cpu->cpsr.t = 1;
}
cpu->nextEvent = cpu->cycles;
cpu->nextEvent -= cpu->cycles;
cpu->cycles = 0;
}
static inline void _ARMReadCPSR(struct ARMCore* cpu) {

View File

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

View File

@ -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) {

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) { \
int currentCycles = ARM_PREFETCH_CYCLES; \
BODY; \
cpu->cycles += currentCycles; \
cpu->cycles -= currentCycles; \
}
#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) { \
int currentCycles = THUMB_PREFETCH_CYCLES; \
BODY; \
cpu->cycles += currentCycles; \
cpu->cycles -= currentCycles; \
}
#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) {
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;
}

View File

@ -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");

View File

@ -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;

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->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;

View File

@ -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) {

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

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->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) {

View File

@ -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);

View File

@ -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;
}
}