GBA Memory: Fix masking of misaligned jumps

This commit is contained in:
Vicki Pfau 2021-03-03 03:06:04 -08:00
parent 7d672a2215
commit dd1d1a0a9d
4 changed files with 7 additions and 4 deletions

View File

@ -48,6 +48,7 @@ Emulation fixes:
- GBA Memory: Mark Famicom Mini games 22 through 28 as non-mirroring - 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: Return correct byte for odd ROM open bus addresses
- GBA Memory: Improved AGBPrint emulation of edge cases (fixes mgba.io/i/1867) - 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 Serialize: Fix alignment check when loading states
- GBA SIO: Fix copying Normal mode transfer values - GBA SIO: Fix copying Normal mode transfer values
- GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800) - GBA SIO: Fix Normal mode being totally broken (fixes mgba.io/i/1800)

View File

@ -56,7 +56,7 @@
#define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode) #define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode)
static inline int32_t ARMWritePC(struct ARMCore* cpu) { 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); cpu->memory.setActiveRegion(cpu, pc);
LOAD_32(cpu->prefetch[0], pc & cpu->memory.activeMask, cpu->memory.activeRegion); LOAD_32(cpu->prefetch[0], pc & cpu->memory.activeMask, cpu->memory.activeRegion);
pc += WORD_SIZE_ARM; pc += WORD_SIZE_ARM;
@ -88,9 +88,11 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution
switch (executionMode) { switch (executionMode) {
case MODE_ARM: case MODE_ARM:
cpu->cpsr.t = 0; cpu->cpsr.t = 0;
cpu->memory.activeMask &= ~2;
break; break;
case MODE_THUMB: case MODE_THUMB:
cpu->cpsr.t = 1; cpu->cpsr.t = 1;
cpu->memory.activeMask |= 2;
} }
cpu->nextEvent = cpu->cycles; cpu->nextEvent = cpu->cycles;
} }

View File

@ -345,6 +345,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion]; cpu->memory.activeSeqCycles16 = memory->waitstatesSeq16[memory->activeRegion];
cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion]; cpu->memory.activeNonseqCycles32 = memory->waitstatesNonseq32[memory->activeRegion];
cpu->memory.activeNonseqCycles16 = memory->waitstatesNonseq16[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 \ #define LOAD_BAD \

View File

@ -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); LOAD_32(gba->cpu->bankedSPSRs[i], i * sizeof(gba->cpu->bankedSPSRs[0]), state->cpu.bankedSPSRs);
} }
gba->cpu->privilegeMode = gba->cpu->cpsr.priv; 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] & 1) {
if (gba->cpu->gprs[ARM_PC] & pcMask) {
mLOG(GBA_STATE, WARN, "Savestate has unaligned PC and is probably corrupted"); 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]); gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
if (state->biosPrefetch) { if (state->biosPrefetch) {