From 2359a4e88689fd23f5cf2ef57f7aa38055158b52 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 2 Jan 2017 21:48:12 -0800 Subject: [PATCH] DS: Move time slicing to event system --- include/mgba/internal/ds/ds.h | 8 ++++ src/ds/core.c | 40 ++---------------- src/ds/ds.c | 80 ++++++++++++++++++++++++++++++++--- 3 files changed, 87 insertions(+), 41 deletions(-) diff --git a/include/mgba/internal/ds/ds.h b/include/mgba/internal/ds/ds.h index e25618b6d..6d0fb977d 100644 --- a/include/mgba/internal/ds/ds.h +++ b/include/mgba/internal/ds/ds.h @@ -69,6 +69,10 @@ struct DS { struct mCoreSync* sync; struct mTiming timing7; struct mTiming timing9; + struct mTimingEvent slice; + struct ARMCore* activeCpu; + uint32_t sliceStart; + int32_t cycleDrift; struct ARMDebugger* debugger; @@ -130,6 +134,10 @@ struct DSCartridge { 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); diff --git a/src/ds/core.c b/src/ds/core.c index 5b0b1efcd..faa91170f 100644 --- a/src/ds/core.c +++ b/src/ds/core.c @@ -15,8 +15,6 @@ #include #include -#define SLICE_CYCLES 2048 - struct DSCore { struct mCore d; struct ARMCore* arm7; @@ -25,7 +23,6 @@ struct DSCore { 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 @@ static bool _DSCoreInit(struct mCore* core) { 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 @@ static void _DSCoreReset(struct mCore* 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 @@ static void _DSCoreRunFrame(struct mCore* 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); } } diff --git a/src/ds/ds.c b/src/ds/ds.c index 09b11f75f..5cf4bc58f 100644 --- a/src/ds/ds.c +++ b/src/ds/ds.c @@ -15,6 +15,8 @@ #include #include +#define SLICE_CYCLES 2048 + mLOG_DEFINE_CATEGORY(DS, "DS"); const uint32_t DS_ARM946ES_FREQUENCY = 0x1FF61FE; @@ -39,17 +41,38 @@ static void DSInit(void* cpu, struct mCPUComponent* component); 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 @@ static void DSInit(void* cpu, struct mCPUComponent* component) { 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 DSDestroy(struct DS* ds) { 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 DS7InterruptHandlerInit(struct ARMInterruptHandler* irqh) { void DS9InterruptHandlerInit(struct ARMInterruptHandler* irqh) { irqh->reset = DS9Reset; - irqh->processEvents = DSProcessEvents; + irqh->processEvents = DS9ProcessEvents; irqh->swi16 = NULL; irqh->swi32 = NULL; irqh->hitIllegal = DSIllegal; @@ -177,6 +206,11 @@ void DS9Reset(struct ARMCore* cpu) { 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) { // TODO: Error check @@ -196,14 +230,28 @@ void DS9Reset(struct ARMCore* cpu) { } } -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 @@ static void DSProcessEvents(struct ARMCore* cpu) { #endif nextEvent = cycles; do { - nextEvent = mTimingTick(&ds->timing7, nextEvent); + nextEvent = mTimingTick(timing, nextEvent); } while (ds->cpuBlocked); cpu->nextEvent = nextEvent; @@ -238,6 +286,28 @@ static void DSProcessEvents(struct ARMCore* cpu) { } } +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) { ds->debugger = (struct ARMDebugger*) debugger->platform; ds->arm7->components[CPU_COMPONENT_DEBUGGER] = &debugger->d;