ARM: Fix LDM^ {pc} differences (fixes #1698)

This commit is contained in:
Vicki Pfau 2020-06-26 01:20:00 -07:00
parent 8ef0427885
commit 5e003d1e7a
2 changed files with 39 additions and 19 deletions

View File

@ -6,6 +6,7 @@ Emulation fixes:
- ARM: Fix ALU reading PC after shifting
- ARM: Fix STR storing PC after address calculation
- ARM: Fix LDM^ writeback to user-mode register
- ARM: Fix LDM^ {pc} differences (fixes mgba.io/i/1698)
- GB: Partially fix timing for skipped BIOS
- GB Memory: Fix OAM DMA from top 8 kB
- GB MBC: Fix MBC1 mode changing behavior

View File

@ -433,11 +433,26 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) {
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## I, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(-, ADDR_MODE_2_IMMEDIATE)), LS, BODY) \
DEFINE_LOAD_STORE_INSTRUCTION_EX_ARM(NAME ## IU, ADDR_MODE_2_RN, ADDR_MODE_2_WRITEBACK(ADDR_MODE_2_INDEX(+, ADDR_MODE_2_IMMEDIATE)), LS, BODY) \
#define ARM_MS_PRE \
#define ARM_MS_PRE_store \
enum PrivilegeMode privilegeMode = cpu->privilegeMode; \
ARMSetPrivilegeMode(cpu, MODE_SYSTEM);
#define ARM_MS_POST ARMSetPrivilegeMode(cpu, privilegeMode);
#define ARM_MS_PRE_load \
enum PrivilegeMode privilegeMode; \
if (!(rs & 0x8000)) { \
privilegeMode = cpu->privilegeMode; \
ARMSetPrivilegeMode(cpu, MODE_SYSTEM); \
}
#define ARM_MS_POST_store ARMSetPrivilegeMode(cpu, privilegeMode);
#define ARM_MS_POST_load \
if ((rs & 0x8000) && _ARMModeHasSPSR(cpu->cpsr.priv)) { \
cpu->cpsr = cpu->spsr; \
_ARMReadCPSR(cpu); \
} else { \
ARMSetPrivilegeMode(cpu, privilegeMode); \
} \
#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, LS, WRITEBACK, S_PRE, S_POST, DIRECTION, POST_BODY) \
DEFINE_INSTRUCTION_ARM(NAME, \
@ -460,14 +475,14 @@ ATTRIBUTE_NOINLINE static void _neutralS(struct ARMCore* cpu, int32_t d) {
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, LS, , , , IB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, , , IB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, LS, , ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, LS, , ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, LS, , ARM_MS_PRE, ARM_MS_POST, IA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, IA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, LS, , ARM_MS_PRE, ARM_MS_POST, IB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE, ARM_MS_POST, IB, POST_BODY)
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, DB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IA, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, LS, , ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IB, POST_BODY) \
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, LS, ADDR_MODE_4_WRITEBACK_ ## NAME, ARM_MS_PRE_ ## LS, ARM_MS_POST_ ## LS, IB, POST_BODY)
// Begin ALU definitions
@ -603,7 +618,11 @@ DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM,
load,
currentCycles += cpu->memory.activeNonseqCycles32 - cpu->memory.activeSeqCycles32;
if ((rs & 0x8000) || !rs) {
if (cpu->executionMode == MODE_THUMB) {
currentCycles += ThumbWritePC(cpu);
} else {
currentCycles += ARMWritePC(cpu);
}
})
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM,