From e81de71f50f1dc7339bb76cda4cd620ce95f1d9a Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Mon, 16 May 2016 01:18:09 -0700 Subject: [PATCH] ARM7: Flush prefetch cache when loading CPSR via MSR --- CHANGES | 1 + src/arm/isa-arm.c | 21 +++++++++++++++++++-- src/arm/isa-inlines.h | 2 -- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 35e65d7d4..6639130c7 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,7 @@ Misc: - GBA Video: Null renderer should return proper register values - Libretro: Disable logging game errors, BIOS calls and stubs in release builds - ARM7: Support forcing Thumb mode via MSR + - ARM7: Flush prefetch cache when loading CPSR via MSR 0.4.0: (2016-02-02) Features: diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index bf826f44b..bce24c608 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -636,7 +636,14 @@ DEFINE_INSTRUCTION_ARM(MSR, ARMSetPrivilegeMode(cpu, (enum PrivilegeMode) ((operand & 0x0000000F) | 0x00000010)); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_PRIV_MASK) | (operand & PSR_PRIV_MASK); } - _ARMReadCPSR(cpu);) + _ARMReadCPSR(cpu); + if (cpu->executionMode == MODE_THUMB) { + LOAD_16(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & cpu->memory.activeMask, cpu->memory.activeRegion); + LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); + } else { + LOAD_32(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & cpu->memory.activeMask, cpu->memory.activeRegion); + LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); + }) DEFINE_INSTRUCTION_ARM(MSRR, int c = opcode & 0x00010000; @@ -663,11 +670,21 @@ DEFINE_INSTRUCTION_ARM(MSRI, if (mask & PSR_USER_MASK) { cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_USER_MASK) | (operand & PSR_USER_MASK); } + if (mask & PSR_STATE_MASK) { + cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_STATE_MASK) | (operand & PSR_STATE_MASK); + } if (cpu->privilegeMode != MODE_USER && (mask & PSR_PRIV_MASK)) { ARMSetPrivilegeMode(cpu, (enum PrivilegeMode) ((operand & 0x0000000F) | 0x00000010)); cpu->cpsr.packed = (cpu->cpsr.packed & ~PSR_PRIV_MASK) | (operand & PSR_PRIV_MASK); } - _ARMReadCPSR(cpu);) + _ARMReadCPSR(cpu); + if (cpu->executionMode == MODE_THUMB) { + LOAD_16(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & cpu->memory.activeMask, cpu->memory.activeRegion); + LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); + } else { + LOAD_32(cpu->prefetch[0], (cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & cpu->memory.activeMask, cpu->memory.activeRegion); + LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); + }) DEFINE_INSTRUCTION_ARM(MSRRI, int c = opcode & 0x00010000; diff --git a/src/arm/isa-inlines.h b/src/arm/isa-inlines.h index 2e7395a00..42a581b4a 100644 --- a/src/arm/isa-inlines.h +++ b/src/arm/isa-inlines.h @@ -85,8 +85,6 @@ static inline void _ARMSetMode(struct ARMCore* cpu, enum ExecutionMode execution break; case MODE_THUMB: cpu->cpsr.t = 1; - cpu->prefetch[0] &= 0xFFFF; - cpu->prefetch[1] &= 0xFFFF; } cpu->nextEvent = cpu->cycles; }