diff --git a/CHANGES b/CHANGES index 4b80c29dd..83fa6f8da 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ Bugfixes: - GBA BIOS: Fix HLE Lz77 and RL functions to properly account for width and invalid addresses - ARM7: Fix LDM writeback to a register already written - GBA Memory: Don't call into GPIO write calls if GPIO devices are absent + - ARM7: Extend prefetch by one stage Misc: - Qt: Disable sync to video by default - GBA: Exit cleanly on FATAL if the port supports it diff --git a/src/arm/arm.c b/src/arm/arm.c index f2b71bc61..17aa099b8 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -176,9 +176,10 @@ void ARMRaiseSWI(struct ARMCore* cpu) { } static inline void ARMStep(struct ARMCore* cpu) { - uint32_t opcode = cpu->prefetch; - LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); + uint32_t opcode = cpu->prefetch[0]; + cpu->prefetch[0] = cpu->prefetch[1]; cpu->gprs[ARM_PC] += WORD_SIZE_ARM; + LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); unsigned condition = opcode >> 28; if (condition != 0xE) { @@ -239,9 +240,10 @@ static inline void ARMStep(struct ARMCore* cpu) { } static inline void ThumbStep(struct ARMCore* cpu) { - uint32_t opcode = cpu->prefetch; - LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); + uint32_t opcode = cpu->prefetch[0]; + cpu->prefetch[0] = cpu->prefetch[1]; cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; + LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); ThumbInstruction instruction = _thumbTable[opcode >> 6]; instruction(cpu, opcode); } diff --git a/src/arm/arm.h b/src/arm/arm.h index 1140b2237..23efd086a 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -149,7 +149,7 @@ struct ARMCore { int32_t shifterOperand; int32_t shifterCarryOut; - uint32_t prefetch; + uint32_t prefetch[2]; enum ExecutionMode executionMode; enum PrivilegeMode privilegeMode; diff --git a/src/arm/isa-inlines.h b/src/arm/isa-inlines.h index 1d72cd62f..6c2327a82 100644 --- a/src/arm/isa-inlines.h +++ b/src/arm/isa-inlines.h @@ -52,15 +52,17 @@ #define ARM_WRITE_PC \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM); \ cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \ - LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ + LOAD_32(cpu->prefetch[0], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ cpu->gprs[ARM_PC] += WORD_SIZE_ARM; \ + LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ currentCycles += 2 + cpu->memory.activeUncachedCycles32 + cpu->memory.activeSeqCycles32; #define THUMB_WRITE_PC \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB); \ cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \ - LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ + LOAD_16(cpu->prefetch[0], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; \ + LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \ currentCycles += 2 + cpu->memory.activeUncachedCycles16 + cpu->memory.activeSeqCycles16; static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) { diff --git a/src/gba/gba-memory.c b/src/gba/gba-memory.c index d3b092a1a..b3293879f 100644 --- a/src/gba/gba-memory.c +++ b/src/gba/gba-memory.c @@ -14,7 +14,7 @@ #include "util/memory.h" static uint32_t _popcount32(unsigned bits); -static uint32_t _deadbeef = 0xDEADBEEF; +static uint32_t _deadbeef[2] = { 0xDEADBEEF, 0xFEEDFACE }; static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region); static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info); @@ -128,7 +128,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { return; } if (memory->activeRegion == REGION_BIOS) { - memory->biosPrefetch = cpu->prefetch; + memory->biosPrefetch = cpu->prefetch[0]; } memory->activeRegion = newRegion; switch (address & ~OFFSET_MASK) { @@ -158,7 +158,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { cpu->memory.activeMask = SIZE_CART0 - 1; break; default: - cpu->memory.activeRegion = &_deadbeef; + cpu->memory.activeRegion = _deadbeef; cpu->memory.activeMask = 0; GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address"); break; @@ -176,7 +176,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { if (cpu->cycles >= cpu->nextEvent) { \ value = gba->bus; \ } else { \ - value = cpu->prefetch; \ + value = cpu->prefetch[0]; \ if (cpu->executionMode == MODE_THUMB) { \ value |= value << 16; \ } \ @@ -303,7 +303,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { if (cpu->cycles >= cpu->nextEvent) { value = gba->bus; } else { - value = cpu->prefetch; + value = cpu->prefetch[0]; } } break; @@ -359,7 +359,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { if (cpu->cycles >= cpu->nextEvent) { value = gba->bus; } else { - value = cpu->prefetch; + value = cpu->prefetch[0]; } break; } @@ -396,7 +396,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { if (cpu->cycles >= cpu->nextEvent) { value = gba->bus; } else { - value = cpu->prefetch; + value = cpu->prefetch[0]; } } break; @@ -454,7 +454,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { if (cpu->cycles >= cpu->nextEvent) { value = gba->bus; } else { - value = cpu->prefetch; + value = cpu->prefetch[0]; } break; } diff --git a/src/gba/gba-serialize.c b/src/gba/gba-serialize.c index 61c716da3..ccf0b708f 100644 --- a/src/gba/gba-serialize.c +++ b/src/gba/gba-serialize.c @@ -82,10 +82,12 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) { gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]); if (gba->cpu->cpsr.t) { gba->cpu->executionMode = MODE_THUMB; - LOAD_16(gba->cpu->prefetch, (gba->cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion); + LOAD_16(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion); + LOAD_16(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion); } else { gba->cpu->executionMode = MODE_ARM; - LOAD_32(gba->cpu->prefetch, (gba->cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion); + LOAD_32(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion); + LOAD_32(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion); } GBAMemoryDeserialize(&gba->memory, state); diff --git a/src/gba/gba.c b/src/gba/gba.c index 541f1ac2f..643782aae 100644 --- a/src/gba/gba.c +++ b/src/gba/gba.c @@ -227,9 +227,9 @@ static void GBAProcessEvents(struct ARMCore* cpu) { int32_t nextEvent = INT_MAX; int32_t testEvent; - gba->bus = cpu->prefetch; + gba->bus = cpu->prefetch[0]; if (cpu->executionMode == MODE_THUMB) { - gba->bus |= cpu->prefetch << 16; + gba->bus |= cpu->prefetch[0] << 16; } if (gba->springIRQ) {