DS: Move time slicing to event system
Jeffrey Pfau jeffrey@endrift.com
Mon, 02 Jan 2017 21:48:12 -0800
3 files changed,
87 insertions(+),
41 deletions(-)
M
include/mgba/internal/ds/ds.h
→
include/mgba/internal/ds/ds.h
@@ -69,6 +69,10 @@
struct mCoreSync* sync; struct mTiming timing7; struct mTiming timing9; + struct mTimingEvent slice; + struct ARMCore* activeCpu; + uint32_t sliceStart; + int32_t cycleDrift; struct ARMDebugger* debugger;@@ -129,6 +133,10 @@ };
void DSCreate(struct DS* ds); void DSDestroy(struct DS* ds); + +void DSRunLoop(struct DS* ds); +void DS7Step(struct DS* ds); +void DS9Step(struct DS* ds); void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger); void DSDetachDebugger(struct DS* ds);
M
src/ds/core.c
→
src/ds/core.c
@@ -15,8 +15,6 @@ #include <mgba-util/memory.h>
#include <mgba-util/patch.h> #include <mgba-util/vfs.h> -#define SLICE_CYCLES 2048 - struct DSCore { struct mCore d; struct ARMCore* arm7;@@ -25,7 +23,6 @@ int keys;
struct mCPUComponent* components[CPU_COMPONENT_MAX]; struct mDebuggerPlatform* debuggerPlatform; struct mCheatDevice* cheatDevice; - int32_t cycleDrift; }; static bool _DSCoreInit(struct mCore* core) {@@ -47,7 +44,6 @@ dscore->arm7 = arm7;
dscore->arm9 = arm9; dscore->debuggerPlatform = NULL; dscore->cheatDevice = NULL; - dscore->cycleDrift = 0; DSCreate(ds); memset(dscore->components, 0, sizeof(dscore->components));@@ -165,7 +161,6 @@ struct DSCore* dscore = (struct DSCore*) core;
struct DS* ds = (struct DS*) core->board; ARMReset(ds->arm7); ARMReset(ds->arm9); - dscore->cycleDrift = 0; } static void _DSCoreRunFrame(struct mCore* core) {@@ -173,47 +168,20 @@ struct DSCore* dscore = (struct DSCore*) core;
struct DS* ds = core->board; int32_t frameCounter = ds->video.frameCounter; while (ds->video.frameCounter == frameCounter) { - if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, SLICE_CYCLES); - } - if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; - } + DSRunLoop(core->board); } } static void _DSCoreRunLoop(struct mCore* core) { - struct DSCore* dscore = (struct DSCore*) core; - if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, SLICE_CYCLES); - } - if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; - } + DSRunLoop(core->board); } static void _DSCoreStep(struct mCore* core) { struct DSCore* dscore = (struct DSCore*) core; if (core->cpu == dscore->arm9) { - do { - if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, dscore->cycleDrift >> 1) << 1; - } - if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, 1); - break; - } - } while (dscore->cycleDrift >= SLICE_CYCLES); + DS9Step(core->board); } else { - do { - if (dscore->cycleDrift < SLICE_CYCLES) { - dscore->cycleDrift += ARMv5RunCycles(dscore->arm9, SLICE_CYCLES - dscore->cycleDrift); - } - if (dscore->cycleDrift >= SLICE_CYCLES) { - dscore->cycleDrift -= ARMv4RunCycles(dscore->arm7, 1) << 1; - break; - } - } while (dscore->cycleDrift < SLICE_CYCLES); + DS7Step(core->board); } }
M
src/ds/ds.c
→
src/ds/ds.c
@@ -15,6 +15,8 @@ #include <mgba-util/memory.h>
#include <mgba-util/math.h> #include <mgba-util/vfs.h> +#define SLICE_CYCLES 2048 + mLOG_DEFINE_CATEGORY(DS, "DS"); const uint32_t DS_ARM946ES_FREQUENCY = 0x1FF61FE;@@ -39,17 +41,38 @@
static void DS7Reset(struct ARMCore* cpu); static void DS7TestIRQ(struct ARMCore* cpu); static void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh); +static void DS7ProcessEvents(struct ARMCore* cpu); static void DS9Reset(struct ARMCore* cpu); static void DS9TestIRQ(struct ARMCore* cpu); static void DS9WriteCP15(struct ARMCore* cpu, int crn, int crm, int opcode1, int opcode2, uint32_t value); static void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh); +static void DS9ProcessEvents(struct ARMCore* cpu); -static void DSProcessEvents(struct ARMCore* cpu); +static void DSProcessEvents(struct DS* ds, struct mTiming* timing); static void DSHitStub(struct ARMCore* cpu, uint32_t opcode); static void DSIllegal(struct ARMCore* cpu, uint32_t opcode); static void DSBreakpoint(struct ARMCore* cpu, int immediate); +static void _slice(struct mTiming* timing, void* context, uint32_t cyclesLate) { + UNUSED(cyclesLate); + struct DS* ds = context; + uint32_t cycles = mTimingCurrentTime(timing) - ds->sliceStart; + if (ds->activeCpu == ds->arm9) { + ds->activeCpu = ds->arm7; + ds->cycleDrift += cycles; + cycles = ds->cycleDrift >> 1; + timing = &ds->timing7; + } else { + ds->activeCpu = ds->arm9; + ds->cycleDrift -= cycles << 1; + cycles = ds->cycleDrift + SLICE_CYCLES; + timing = &ds->timing9; + } + mTimingSchedule(timing, &ds->slice, cycles); + ds->sliceStart = mTimingCurrentTime(timing); +} + void DSCreate(struct DS* ds) { ds->d.id = DS_COMPONENT_MAGIC; ds->d.init = DSInit;@@ -69,9 +92,15 @@ ds->sync = 0;
return; } ds->arm9 = cpu; + ds->activeCpu = NULL; ds->arm9->cp15.r1.c0 = ARMControlRegFillVE(0); + ds->slice.name = "DS CPU Time Slicing"; + ds->slice.callback = _slice; + ds->slice.context = ds; + ds->slice.priority = UINT_MAX; + DS7InterruptHandlerInit(&ds->arm7->irqh); DS9InterruptHandlerInit(&ds->arm9->irqh); DSMemoryInit(ds);@@ -109,7 +138,7 @@ }
void DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) { irqh->reset = DS7Reset; - irqh->processEvents = DSProcessEvents; + irqh->processEvents = DS7ProcessEvents; irqh->swi16 = DS7Swi16; irqh->swi32 = DS7Swi32; irqh->hitIllegal = DSIllegal;@@ -122,7 +151,7 @@ }
void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh) { irqh->reset = DS9Reset; - irqh->processEvents = DSProcessEvents; + irqh->processEvents = DS9ProcessEvents; irqh->swi16 = NULL; irqh->swi32 = NULL; irqh->hitIllegal = DSIllegal;@@ -176,6 +205,11 @@
struct DS* ds = (struct DS*) cpu->master; mTimingClear(&ds->timing9); DS9IOInit(ds); + + ds->activeCpu = cpu; + mTimingSchedule(&ds->timing9, &ds->slice, SLICE_CYCLES); + ds->cycleDrift = 0; + ds->sliceStart = mTimingCurrentTime(&ds->timing9); struct DSCartridge* header = ds->romVf->map(ds->romVf, sizeof(*header), MAP_READ); if (header) {@@ -196,14 +230,28 @@ ds->romVf->unmap(ds->romVf, header, sizeof(*header));
} } -static void DSProcessEvents(struct ARMCore* cpu) { +static void DS7ProcessEvents(struct ARMCore* cpu) { struct DS* ds = (struct DS*) cpu->master; if (ds->springIRQ7 && !cpu->cpsr.i) { ARMRaiseIRQ(cpu); ds->springIRQ7 = 0; } + DSProcessEvents(ds, &ds->timing7); +} +static void DS9ProcessEvents(struct ARMCore* cpu) { + struct DS* ds = (struct DS*) cpu->master; + + if (ds->springIRQ9 && !cpu->cpsr.i) { + ARMRaiseIRQ(cpu); + ds->springIRQ9 = 0; + } + DSProcessEvents(ds, &ds->timing9); +} + +static void DSProcessEvents(struct DS* ds, struct mTiming* timing) { + struct ARMCore* cpu = ds->activeCpu; int32_t nextEvent = cpu->nextEvent; while (cpu->cycles >= nextEvent) { int32_t cycles = cpu->cycles;@@ -218,7 +266,7 @@ }
#endif nextEvent = cycles; do { - nextEvent = mTimingTick(&ds->timing7, nextEvent); + nextEvent = mTimingTick(timing, nextEvent); } while (ds->cpuBlocked); cpu->nextEvent = nextEvent;@@ -236,6 +284,28 @@ mLOG(DS, FATAL, "Negative cycles will pass: %i", nextEvent);
} #endif } +} + +void DSRunLoop(struct DS* ds) { + if (ds->activeCpu == ds->arm9) { + ARMv5RunLoop(ds->arm9); + } else { + ARMv4RunLoop(ds->arm7); + } +} + +void DS7Step(struct DS* ds) { + while (ds->activeCpu == ds->arm9) { + ARMv5RunLoop(ds->arm9); + } + ARMv4Run(ds->arm7); +} + +void DS9Step(struct DS* ds) { + while (ds->activeCpu == ds->arm7) { + ARMv4RunLoop(ds->arm7); + } + ARMv5Run(ds->arm9); } void DSAttachDebugger(struct DS* ds, struct mDebugger* debugger) {