From 25885e1e82b3cef2e2efc4abafa8e615e714e5fd Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Fri, 27 Sep 2013 23:48:56 -0700 Subject: [PATCH] Invalid memory reads --- src/arm/arm.h | 1 + src/arm/isa-arm.c | 3 ++- src/arm/isa-thumb.c | 7 +++---- src/gba/gba-memory.c | 22 +++++++++++++++++++++- src/gba/gba-memory.h | 1 + 5 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/arm/arm.h b/src/arm/arm.h index 98c22a5f5..99b3d5a1d 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -111,6 +111,7 @@ struct ARMCore { int32_t shifterOperand; int32_t shifterCarryOut; + uint32_t currentPC; enum ExecutionMode executionMode; enum PrivilegeMode privilegeMode; diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index 78f7e8db6..5b8f0c787 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -194,7 +194,8 @@ static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory* memory, uint32_t void ARMStep(struct ARMCore* cpu) { // TODO uint32_t opcode; - ARMInstruction instruction = _ARMLoadInstructionARM(cpu->memory, cpu->gprs[ARM_PC] - WORD_SIZE_ARM, &opcode); + cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_ARM; + ARMInstruction instruction = _ARMLoadInstructionARM(cpu->memory, cpu->currentPC, &opcode); cpu->gprs[ARM_PC] += WORD_SIZE_ARM; int condition = opcode >> 28; diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index 29f23edcc..d0334647c 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -5,10 +5,9 @@ static const ThumbInstruction _thumbTable[0x400]; void ThumbStep(struct ARMCore* cpu) { - uint32_t address = cpu->gprs[ARM_PC]; - cpu->gprs[ARM_PC] = address + WORD_SIZE_THUMB; - address -= WORD_SIZE_THUMB; - uint16_t opcode = ((uint16_t*) cpu->memory->activeRegion)[(address & cpu->memory->activeMask) >> 1]; + cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_THUMB; + cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; + uint16_t opcode = ((uint16_t*) cpu->memory->activeRegion)[(cpu->currentPC & cpu->memory->activeMask) >> 1]; ThumbInstruction instruction = _thumbTable[opcode >> 6]; instruction(cpu, opcode); } diff --git a/src/gba/gba-memory.c b/src/gba/gba-memory.c index d1cc76fac..e5fe195a7 100644 --- a/src/gba/gba-memory.c +++ b/src/gba/gba-memory.c @@ -67,6 +67,7 @@ void GBAMemoryInit(struct GBAMemory* memory) { memory->d.setActiveRegion = GBASetActiveRegion; memory->d.activePrefetchCycles32 = 0; memory->d.activePrefetchCycles16 = 0; + memory->biosPrefetch = 0; memory->d.waitMultiple = GBAWaitMultiple; } @@ -79,6 +80,9 @@ void GBAMemoryDeinit(struct GBAMemory* memory) { static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + if (gbaMemory->activeRegion == REGION_BIOS) { + gbaMemory->biosPrefetch = memory->load32(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_ARM * 2, 0); + } gbaMemory->activeRegion = address >> BASE_OFFSET; memory->activePrefetchCycles32 = gbaMemory->waitstatesPrefetch32[gbaMemory->activeRegion]; memory->activePrefetchCycles16 = gbaMemory->waitstatesPrefetch16[gbaMemory->activeRegion]; @@ -121,7 +125,15 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter) switch (address & ~OFFSET_MASK) { case BASE_BIOS: - GBALog(gbaMemory->p, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address); + if (gbaMemory->p->cpu.currentPC >> BASE_OFFSET == REGION_BIOS) { + if (address < hleBiosLength) { + value = gbaMemory->bios[address >> 2]; + } else { + value = 0; + } + } else { + value = gbaMemory->biosPrefetch; + } break; case BASE_WORKING_RAM: value = gbaMemory->wram[(address & (SIZE_WORKING_RAM - 1)) >> 2]; @@ -158,6 +170,12 @@ int32_t GBALoad32(struct ARMMemory* memory, uint32_t address, int* cycleCounter) break; default: GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); + if (gbaMemory->p->cpu.executionMode == MODE_ARM) { + value = memory->load32(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_ARM * 2, 0); + } else { + value = memory->load16(memory, gbaMemory->p->cpu.currentPC + WORD_SIZE_THUMB * 2, 0); + value |= value << 16; + } break; } @@ -225,6 +243,7 @@ int16_t GBALoad16(struct ARMMemory* memory, uint32_t address, int* cycleCounter) break; default: GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); + value = memory->load16(memory, gbaMemory->p->cpu.currentPC + (gbaMemory->p->cpu.executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0); break; } @@ -292,6 +311,7 @@ int8_t GBALoad8(struct ARMMemory* memory, uint32_t address, int* cycleCounter) { break; default: GBALog(gbaMemory->p, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address); + value = memory->load16(memory, gbaMemory->p->cpu.currentPC + (gbaMemory->p->cpu.executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0) >> ((address & 1) << 3); break; } diff --git a/src/gba/gba-memory.h b/src/gba/gba-memory.h index 6392600ff..eb3aee072 100644 --- a/src/gba/gba-memory.h +++ b/src/gba/gba-memory.h @@ -122,6 +122,7 @@ struct GBAMemory { char waitstatesPrefetch32[256]; char waitstatesPrefetch16[256]; int activeRegion; + uint32_t biosPrefetch; struct GBADMA dma[4]; };