Reimplement prefetch, temporarily removing busy loop optimization
Jeffrey Pfau jeffrey@endrift.com
Thu, 28 Aug 2014 05:45:37 -0700
4 files changed,
28 insertions(+),
29 deletions(-)
M
src/arm/arm.c
→
src/arm/arm.c
@@ -117,7 +117,6 @@
cpu->executionMode = MODE_THUMB; _ARMSetMode(cpu, MODE_ARM); - cpu->currentPC = 0; int currentCycles = 0; ARM_WRITE_PC;@@ -142,7 +141,9 @@ }
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 @@ }
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 @@ cpu->cpsr.i = 1;
} 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 @@ instruction(cpu, opcode);
} 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); }
M
src/arm/arm.h
→
src/arm/arm.h
@@ -133,7 +133,7 @@
int32_t shifterOperand; int32_t shifterCarryOut; - uint32_t currentPC; + uint32_t prefetch; enum ExecutionMode executionMode; enum PrivilegeMode privilegeMode;
M
src/arm/isa-inlines.h
→
src/arm/isa-inlines.h
@@ -44,13 +44,17 @@ #define ARM_STUB cpu->irqh.hitStub(cpu, opcode)
#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) {
M
src/gba/gba-memory.c
→
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 @@ int wait = 0;
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 @@ GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address);
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 @@ int wait = 0;
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 @@ GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load16: 0x%08X", address);
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 @@ int wait = 0;
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 @@ }
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; }