From baa71027e38ff1b91546c65b7b799883b98d3c3e Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Thu, 28 Aug 2014 05:45:37 -0700 Subject: [PATCH] Reimplement prefetch, temporarily removing busy loop optimization --- src/arm/arm.c | 21 +++++++++++---------- src/arm/arm.h | 2 +- src/arm/isa-inlines.h | 12 ++++++++---- src/gba/gba-memory.c | 22 ++++++++-------------- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/arm/arm.c b/src/arm/arm.c index 582a044b3..bfcdfd26c 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -117,7 +117,6 @@ void ARMReset(struct ARMCore* cpu) { cpu->executionMode = MODE_THUMB; _ARMSetMode(cpu, MODE_ARM); - cpu->currentPC = 0; int currentCycles = 0; ARM_WRITE_PC; @@ -142,7 +141,9 @@ void ARMRaiseIRQ(struct ARMCore* cpu) { ARMSetPrivilegeMode(cpu, MODE_IRQ); cpu->cpsr.priv = MODE_IRQ; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth + WORD_SIZE_ARM; - cpu->gprs[ARM_PC] = BASE_IRQ + WORD_SIZE_ARM; + cpu->gprs[ARM_PC] = BASE_IRQ; + int currentCycles = 0; + ARM_WRITE_PC; cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); _ARMSetMode(cpu, MODE_ARM); cpu->spsr = cpsr; @@ -160,7 +161,9 @@ void ARMRaiseSWI(struct ARMCore* cpu) { ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); cpu->cpsr.priv = MODE_SUPERVISOR; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth; - cpu->gprs[ARM_PC] = BASE_SWI + WORD_SIZE_ARM; + cpu->gprs[ARM_PC] = BASE_SWI; + int currentCycles = 0; + ARM_WRITE_PC; cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); _ARMSetMode(cpu, MODE_ARM); cpu->spsr = cpsr; @@ -168,12 +171,11 @@ void ARMRaiseSWI(struct ARMCore* cpu) { } static inline void ARMStep(struct ARMCore* cpu) { - uint32_t opcode; - cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_ARM; - LOAD_32(opcode, cpu->currentPC & cpu->memory.activeMask, cpu->memory.activeRegion); + uint32_t opcode = cpu->prefetch; + LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); cpu->gprs[ARM_PC] += WORD_SIZE_ARM; - int condition = opcode >> 28; + unsigned condition = opcode >> 28; if (condition == 0xE) { ARMInstruction instruction = _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; instruction(cpu, opcode); @@ -273,10 +275,9 @@ static inline void ARMStep(struct ARMCore* cpu) { } static inline void ThumbStep(struct ARMCore* cpu) { - cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_THUMB; + uint32_t opcode = cpu->prefetch; + LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; - uint16_t opcode; - LOAD_16(opcode, cpu->currentPC & 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 66c0bfa58..048c5a5f6 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -133,7 +133,7 @@ struct ARMCore { int32_t shifterOperand; int32_t shifterCarryOut; - uint32_t currentPC; + uint32_t prefetch; enum ExecutionMode executionMode; enum PrivilegeMode privilegeMode; diff --git a/src/arm/isa-inlines.h b/src/arm/isa-inlines.h index cfe6da2fa..c50021c92 100644 --- a/src/arm/isa-inlines.h +++ b/src/arm/isa-inlines.h @@ -44,13 +44,17 @@ #define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode) #define ARM_WRITE_PC \ - cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \ - cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC] - WORD_SIZE_ARM); \ + 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); \ + cpu->gprs[ARM_PC] += WORD_SIZE_ARM; \ currentCycles += 2 + cpu->memory.activeUncachedCycles32 + cpu->memory.activeSeqCycles32; #define THUMB_WRITE_PC \ - cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB) + WORD_SIZE_THUMB; \ - cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC] - WORD_SIZE_THUMB); \ + 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); \ + cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; \ 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 740ead2dc..ef692a498 100644 --- a/src/gba/gba-memory.c +++ b/src/gba/gba-memory.c @@ -109,16 +109,12 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; - if (cpu->currentPC == gba->busyLoop) { - GBAHalt(gba); - } - int newRegion = address >> BASE_OFFSET; if (newRegion == memory->activeRegion) { return; } if (memory->activeRegion == REGION_BIOS) { - memory->biosPrefetch = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); + memory->biosPrefetch = cpu->prefetch; } memory->activeRegion = newRegion; switch (address & ~OFFSET_MASK) { @@ -165,7 +161,7 @@ int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { switch (address & ~OFFSET_MASK) { case BASE_BIOS: - if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) { + if (cpu->gprs[ARM_PC] >> BASE_OFFSET == REGION_BIOS) { if (address < SIZE_BIOS) { LOAD_32(value, address, memory->bios); } else { @@ -211,10 +207,8 @@ int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); - if (cpu->executionMode == MODE_ARM) { - value = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); - } else { - value = cpu->memory.load16(cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0); + value = cpu->prefetch; + if (cpu->executionMode == MODE_THUMB) { value |= value << 16; } break; @@ -241,7 +235,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { switch (address & ~OFFSET_MASK) { case BASE_BIOS: - if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) { + if (cpu->gprs[ARM_PC] >> BASE_OFFSET == REGION_BIOS) { if (address < SIZE_BIOS) { LOAD_16(value, address, memory->bios); } else { @@ -294,7 +288,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); - value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0); + value = cpu->prefetch; break; } @@ -318,7 +312,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { switch (address & ~OFFSET_MASK) { case BASE_BIOS: - if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) { + if (cpu->gprs[ARM_PC] >> BASE_OFFSET == REGION_BIOS) { if (address < SIZE_BIOS) { value = ((int8_t*) memory->bios)[address]; } else { @@ -372,7 +366,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address); - value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0) >> ((address & 1) << 3); + value = cpu->prefetch & 0xFF; break; }