all repos — mgba @ d3abd2dc63b0ad2b62e4dd05126d6f76f69e0639

mGBA Game Boy Advance Emulator

Minor ROM access optimization
Jeffrey Pfau jeffrey@endrift.com
Tue, 09 Apr 2013 22:20:35 -0700
commit

d3abd2dc63b0ad2b62e4dd05126d6f76f69e0639

parent

027e27caa409dca18c88f12a32037eb2d32db6f7

4 files changed, 53 insertions(+), 5 deletions(-)

jump to
M src/arm.hsrc/arm.h

@@ -76,6 +76,10 @@

void (*store32)(struct ARMMemory*, uint32_t address, int32_t value); void (*store16)(struct ARMMemory*, uint32_t address, int16_t value); void (*store8)(struct ARMMemory*, uint32_t address, int8_t value); + + uint32_t* activeRegion; + uint32_t activeMask; + void (*setActiveRegion)(struct ARMMemory*, uint32_t address); }; struct ARMBoard {
M src/gba.csrc/gba.c

@@ -5,6 +5,8 @@ #include <unistd.h>

static const char* GBA_CANNOT_MMAP = "Could not map memory"; +static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region); + void GBAInit(struct GBA* gba) { gba->errno = GBA_NO_ERROR; gba->errstr = 0;

@@ -45,6 +47,10 @@ GBAMemoryDeinit(memory);

memory->p->errno = GBA_OUT_OF_MEMORY; memory->p->errstr = GBA_CANNOT_MMAP; } + + memory->d.activeRegion = 0; + memory->d.activeMask = 0; + memory->d.setActiveRegion = GBASetActiveRegion; } void GBAMemoryDeinit(struct GBAMemory* memory) {

@@ -69,6 +75,38 @@

void GBALoadROM(struct GBA* gba, int fd) { gba->memory.rom = mmap(0, SIZE_CART0, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0); // TODO: error check +} + +static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) { + struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + + switch (address & ~OFFSET_MASK) { + case BASE_BIOS: + memory->activeRegion = gbaMemory->bios; + memory->activeMask = 0; + break; + case BASE_WORKING_RAM: + memory->activeRegion = gbaMemory->wram; + memory->activeMask = SIZE_WORKING_RAM - 1; + break; + case BASE_WORKING_IRAM: + memory->activeRegion = gbaMemory->iwram; + memory->activeMask = SIZE_WORKING_IRAM - 1; + break; + case BASE_CART0: + case BASE_CART0_EX: + case BASE_CART1: + case BASE_CART1_EX: + case BASE_CART2: + case BASE_CART2_EX: + memory->activeRegion = gbaMemory->rom; + memory->activeMask = SIZE_CART0 - 1; + break; + default: + memory->activeRegion = 0; + memory->activeMask = 0; + break; + } } int32_t GBALoad32(struct ARMMemory* memory, uint32_t address) {
M src/isa-arm.csrc/isa-arm.c

@@ -29,7 +29,7 @@

static const ARMInstruction _armTable[0x1000]; static ARMInstruction _ARMLoadInstructionARM(struct ARMMemory* memory, uint32_t address, uint32_t* opcodeOut) { - uint32_t opcode = memory->load32(memory, address); + uint32_t opcode = memory->activeRegion[(address & memory->activeMask) >> 2]; *opcodeOut = opcode; return _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; }

@@ -127,7 +127,8 @@ // Instruction definitions

// Beware pre-processor antics #define ARM_WRITE_PC \ - cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM + cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM) + WORD_SIZE_ARM; \ + cpu->memory->setActiveRegion(cpu->memory, cpu->gprs[ARM_PC]); #define ARM_ADDITION_S(M, N, D) \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \
M src/main.csrc/main.c

@@ -2,8 +2,9 @@ #include "arm.h"

#include "gba.h" #include "isa-arm.h" +#include <fcntl.h> #include <sys/stat.h> -#include <fcntl.h> +#include <unistd.h> int main(int argc, char** argv) { struct GBA gba;

@@ -11,9 +12,13 @@ GBAInit(&gba);

int fd = open("test.rom", O_RDONLY); GBALoadROM(&gba, fd); gba.cpu.gprs[ARM_PC] = 0x08000004; - ARMStep(&gba.cpu); - ARMStep(&gba.cpu); + gba.memory.d.setActiveRegion(&gba.memory.d, gba.cpu.gprs[ARM_PC]); + int i; + for (i = 0; i < 1024 * 1024 * 16; ++i) { + ARMStep(&gba.cpu); + } GBADeinit(&gba); + close(fd); return 0; }