all repos — mgba @ baa71027e38ff1b91546c65b7b799883b98d3c3e

mGBA Game Boy Advance Emulator

Reimplement prefetch, temporarily removing busy loop optimization
Jeffrey Pfau jeffrey@endrift.com
Thu, 28 Aug 2014 05:45:37 -0700
commit

baa71027e38ff1b91546c65b7b799883b98d3c3e

parent

ca3e1c428ef6688011f22df1cec5839f69fe87c4

4 files changed, 28 insertions(+), 29 deletions(-)

jump to
M src/arm/arm.csrc/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.hsrc/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.hsrc/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.csrc/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; }