From dd1d1a0a9d28d50e96f05539a27cd1b04911458d Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Wed, 3 Mar 2021 03:06:04 -0800 Subject: [PATCH] GBA Memory: Fix masking of misaligned jumps --- CHANGES | 1 + include/mgba/internal/arm/isa-inlines.h | 4 +++- src/gba/memory.c | 1 + src/gba/serialize.c | 5 ++--- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index ba37f80f4..a42382559 100644 --- a/CHANGES +++ b/CHANGES @@ -48,6 +48,7 @@ Emulation fixes: - GBA Memory: Mark Famicom Mini games 22 through 28 as non-mirroring - GBA Memory: Return correct byte for odd ROM open bus addresses - GBA Memory: Improved AGBPrint emulation of edge cases (fixes mgba.io/i/1867) + - GBA Memory: Fix masking of misaligned jumps - GBA Serialize: Fix alignment check when loading states - GBA SIO: Fix copying Normal mode transfer values - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) diff --git a/include/mgba/internal/arm/isa-inlines.h b/include/mgba/internal/arm/isa-inlines.h index d9b8c9528..2ee6aee7c 100644 --- a/include/mgba/internal/arm/isa-inlines.h +++ b/include/mgba/internal/arm/isa-inlines.h @@ -56,7 +56,7 @@ #define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode) static inline int32_t ARMWritePC(struct ARMCore* cpu) { - uint32_t pc = cpu->gprs[ARM_PC] & -WORD_SIZE_ARM; + uint32_t pc = cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB; cpu->memory.setActiveRegion(cpu, pc); LOAD_32(cpu->prefetch[0], pc & cpu->memory.activeMask, cpu->memory.activeRegion); pc += WORD_SIZE_ARM; @@ -88,9 +88,11 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution switch (executionMode) { case MODE_ARM: cpu->cpsr.t = 0; + cpu->memory.activeMask &= ~2; break; case MODE_THUMB: cpu->cpsr.t = 1; + cpu->memory.activeMask |= 2; } cpu->nextEvent = cpu->cycles; } diff --git a/src/gba/memory.c b/src/gba/memory.c index 1e6455ef7..e6e3a6b2d 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -345,6 +345,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion]; cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion]; cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[memory->activeRegion]; + cpu->memory.activeMask &= -(cpu->executionMode == MODE_THUMB ? WORD_SIZE_THUMB : WORD_SIZE_ARM); } #define LOAD_BAD \ diff --git a/src/gba/serialize.c b/src/gba/serialize.c index f6eafa6a4..022d7b92f 100644 --- a/src/gba/serialize.c +++ b/src/gba/serialize.c @@ -154,10 +154,9 @@ bool GBADeserialize(struct GBA* gba, const struct GBASerializedState* state) { LOAD_32(gba->cpu->bankedSPSRs[i], i * sizeof(gba->cpu->bankedSPSRs[0]), state->cpu.bankedSPSRs); } gba->cpu->privilegeMode = gba->cpu->cpsr.priv; - uint32_t pcMask = (gba->cpu->cpsr.t ? WORD_SIZE_THUMB : WORD_SIZE_ARM) - 1; - if (gba->cpu->gprs[ARM_PC] & pcMask) { + if (gba->cpu->gprs[ARM_PC] & 1) { mLOG(GBA_STATE, WARN, "Savestate has unaligned PC and is probably corrupted"); - gba->cpu->gprs[ARM_PC] &= ~pcMask; + gba->cpu->gprs[ARM_PC] &= ~1; } gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); if (state->biosPrefetch) {