all repos — mgba @ ecc4775c311cb2c9cef70c8d4a4dc53fedeb2a38

mGBA Game Boy Advance Emulator

Start implementing instruction timing
Jeffrey Pfau jeffrey@endrift.com
Sun, 14 Apr 2013 23:12:03 -0700
commit

ecc4775c311cb2c9cef70c8d4a4dc53fedeb2a38

parent

fa64310e83f00f8ead49dace975036022f0faed5

M src/arm/arm.csrc/arm/arm.c

@@ -4,6 +4,8 @@ #include "isa-arm.h"

#include "isa-inlines.h" #include "isa-thumb.h" +#include <limits.h> + static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode); void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) {

@@ -97,7 +99,8 @@

cpu->cpsr.packed = MODE_SYSTEM; cpu->spsr.packed = 0; - cpu->cyclesToEvent = 0; + cpu->cycles = 0; + cpu->nextEvent = INT_MAX; cpu->shifterOperand = 0; cpu->shifterCarryOut = 0;
M src/arm/arm.hsrc/arm/arm.h

@@ -79,12 +79,15 @@ void (*store8)(struct ARMMemory*, uint32_t address, int8_t value);

uint32_t* activeRegion; uint32_t activeMask; + uint32_t activePrefetchCycles32; + uint32_t activePrefetchCycles16; void (*setActiveRegion)(struct ARMMemory*, uint32_t address); }; struct ARMBoard { struct ARMCore* cpu; void (*reset)(struct ARMBoard* board); + void (*nextEvent)(struct ARMBoard* board); void (*swi16)(struct ARMBoard* board, int immediate); void (*swi32)(struct ARMBoard* board, int immediate);

@@ -96,7 +99,8 @@ int32_t gprs[16];

union PSR cpsr; union PSR spsr; - int32_t cyclesToEvent; + uint32_t cycles; + uint32_t nextEvent; int32_t bankedRegisters[6][7]; int32_t bankedSPSRs[6];
M src/arm/isa-arm.csrc/arm/isa-arm.c

@@ -106,71 +106,85 @@ } else {

switch (condition) { case 0x0: if (!ARM_COND_EQ) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x1: if (!ARM_COND_NE) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x2: if (!ARM_COND_CS) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x3: if (!ARM_COND_CC) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x4: if (!ARM_COND_MI) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x5: if (!ARM_COND_PL) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x6: if (!ARM_COND_VS) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x7: if (!ARM_COND_VC) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x8: if (!ARM_COND_HI) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0x9: if (!ARM_COND_LS) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0xA: if (!ARM_COND_GE) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0xB: if (!ARM_COND_LT) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0xC: if (!ARM_COND_GT) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break; case 0xD: if (!ARM_COND_GE) { + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; return; } break;

@@ -237,6 +251,7 @@

#define DEFINE_INSTRUCTION_ARM(NAME, BODY) \ static void _ARMInstruction ## NAME (struct ARMCore* cpu, uint32_t opcode) { \ BODY; \ + cpu->cycles += 1 + cpu->memory->activePrefetchCycles32; \ } #define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY, POST_BODY) \
M src/arm/isa-thumb.csrc/arm/isa-thumb.c

@@ -95,6 +95,7 @@

#define DEFINE_INSTRUCTION_THUMB(NAME, BODY) \ static void _ThumbInstruction ## NAME (struct ARMCore* cpu, uint16_t opcode) { \ BODY; \ + cpu->cycles += 1 + cpu->memory->activePrefetchCycles16; \ } #define DEFINE_IMMEDIATE_5_INSTRUCTION_EX_THUMB(NAME, IMMEDIATE, BODY) \
M src/gba/gba-memory.csrc/gba/gba-memory.c

@@ -9,6 +9,9 @@ static const char* GBA_CANNOT_MMAP = "Could not map memory";

static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t region); +static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 }; +static const char GBA_BASE_WAITSTATES_SEQ[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4 }; + void GBAMemoryInit(struct GBAMemory* memory) { memory->d.load32 = GBALoad32; memory->d.load16 = GBALoad16;

@@ -31,6 +34,20 @@ memory->p->errno = GBA_OUT_OF_MEMORY;

memory->p->errstr = GBA_CANNOT_MMAP; } + int i; + for (i = 0; i < 16; ++i) { + memory->waitstates16[i] = GBA_BASE_WAITSTATES[i]; + memory->waitstatesSeq16[i] = GBA_BASE_WAITSTATES_SEQ[i]; + memory->waitstates32[i] = GBA_BASE_WAITSTATES[i] + GBA_BASE_WAITSTATES_SEQ[i] + 1; + memory->waitstatesSeq32[i] = GBA_BASE_WAITSTATES_SEQ[i] + GBA_BASE_WAITSTATES_SEQ[i] + 1; + } + for (; i < 256; ++i) { + memory->waitstates16[i] = 0; + memory->waitstatesSeq16[i] = 0; + memory->waitstates32[i] = 0; + memory->waitstatesSeq32[i] = 0; + } + memory->d.activeRegion = 0; memory->d.activeMask = 0; memory->d.setActiveRegion = GBASetActiveRegion;

@@ -44,6 +61,8 @@

static void GBASetActiveRegion(struct ARMMemory* memory, uint32_t address) { struct GBAMemory* gbaMemory = (struct GBAMemory*) memory; + memory->activePrefetchCycles32 = gbaMemory->waitstates32[address >> BASE_OFFSET]; + memory->activePrefetchCycles16 = gbaMemory->waitstates16[address >> BASE_OFFSET]; switch (address & ~OFFSET_MASK) { case BASE_BIOS: memory->activeRegion = gbaMemory->bios;
M src/gba/gba-memory.hsrc/gba/gba-memory.h

@@ -55,7 +55,8 @@ SIZE_CART_EEPROM = 0x00002000

}; enum { - OFFSET_MASK = 0x00FFFFFF + OFFSET_MASK = 0x00FFFFFF, + BASE_OFFSET = 24 }; struct GBAMemory {

@@ -67,6 +68,11 @@ uint32_t* wram;

uint32_t* iwram; uint32_t* rom; uint16_t io[SIZE_IO >> 1]; + + char waitstates32[256]; + char waitstates16[256]; + char waitstatesSeq32[256]; + char waitstatesSeq16[256]; }; int32_t GBALoad32(struct ARMMemory* memory, uint32_t address);