DS: Move time slicing to event system

This commit is contained in:
Jeffrey Pfau 2017-01-02 21:48:12 -08:00
parent d620a8c38c
commit 2359a4e886
3 changed files with 87 additions and 41 deletions

View File

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

View File

@ -15,8 +15,6 @@
#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 @@ 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);
}
}

View File

@ -15,6 +15,8 @@
#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 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;