diff --git a/CHANGES b/CHANGES index 804b6bc18..db9fe99c6 100644 --- a/CHANGES +++ b/CHANGES @@ -77,6 +77,7 @@ Misc: - Qt: Don't save window size when entering fullscreen - Qt: Make the default fullscreen binding for Windows be Alt-Enter - GBA Video: Refactor software renderer into separate files + - ARM7: Add emulation for Undefined CPU mode 0.2.1: (2015-05-13) Bugfixes: diff --git a/src/arm/arm.c b/src/arm/arm.c index b75274aa3..118383cd7 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -190,6 +190,26 @@ void ARMRaiseSWI(struct ARMCore* cpu) { cpu->cycles += currentCycles; } +void ARMRaiseUndefined(struct ARMCore* cpu) { + union PSR cpsr = cpu->cpsr; + int instructionWidth; + if (cpu->executionMode == MODE_THUMB) { + instructionWidth = WORD_SIZE_THUMB; + } else { + instructionWidth = WORD_SIZE_ARM; + } + ARMSetPrivilegeMode(cpu, MODE_UNDEFINED); + cpu->cpsr.priv = MODE_UNDEFINED; + cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth; + cpu->gprs[ARM_PC] = BASE_UNDEF; + int currentCycles = 0; + ARM_WRITE_PC; + _ARMSetMode(cpu, MODE_ARM); + cpu->spsr = cpsr; + cpu->cpsr.i = 1; + cpu->cycles += currentCycles; +} + static inline void ARMStep(struct ARMCore* cpu) { uint32_t opcode = cpu->prefetch[0]; cpu->prefetch[0] = cpu->prefetch[1]; diff --git a/src/arm/arm.h b/src/arm/arm.h index 2242bf1fb..ec04f5d72 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -172,6 +172,7 @@ void ARMReset(struct ARMCore* cpu); void ARMSetPrivilegeMode(struct ARMCore*, enum PrivilegeMode); void ARMRaiseIRQ(struct ARMCore*); void ARMRaiseSWI(struct ARMCore*); +void ARMRaiseUndefined(struct ARMCore*); void ARMRun(struct ARMCore* cpu); void ARMRunLoop(struct ARMCore* cpu); diff --git a/src/gba/gba.c b/src/gba/gba.c index 3613adbec..c1a620b58 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -650,7 +650,7 @@ void GBAGetGameTitle(struct GBA* gba, char* out) { void GBAHitStub(struct ARMCore* cpu, uint32_t opcode) { struct GBA* gba = (struct GBA*) cpu->master; - enum GBALogLevel level = GBA_LOG_FATAL; + enum GBALogLevel level = GBA_LOG_ERROR; if (gba->debugger) { level = GBA_LOG_STUB; struct DebuggerEntryInfo info = { @@ -671,6 +671,8 @@ void GBAIllegal(struct ARMCore* cpu, uint32_t opcode) { .opcode = opcode }; ARMDebuggerEnter(gba->debugger, DEBUGGER_ENTER_ILLEGAL_OP, &info); + } else { + ARMRaiseUndefined(cpu); } }