From ecc4775c311cb2c9cef70c8d4a4dc53fedeb2a38 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Sun, 14 Apr 2013 23:12:03 -0700 Subject: [PATCH] Start implementing instruction timing --- src/arm/arm.c | 5 ++++- src/arm/arm.h | 6 +++++- src/arm/isa-arm.c | 15 +++++++++++++++ src/arm/isa-thumb.c | 1 + src/gba/gba-memory.c | 19 +++++++++++++++++++ src/gba/gba-memory.h | 8 +++++++- 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/arm/arm.c b/src/arm/arm.c index 038019d95..b16c026c7 100644 --- a/src/arm/arm.c +++ b/src/arm/arm.c @@ -4,6 +4,8 @@ #include "isa-inlines.h" #include "isa-thumb.h" +#include + static inline enum RegisterBank _ARMSelectBank(enum PrivilegeMode); void ARMSetPrivilegeMode(struct ARMCore* cpu, enum PrivilegeMode mode) { @@ -97,7 +99,8 @@ void ARMReset(struct ARMCore* cpu) { 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; diff --git a/src/arm/arm.h b/src/arm/arm.h index 36bdf9ce0..2635da3f8 100644 --- a/src/arm/arm.h +++ b/src/arm/arm.h @@ -79,12 +79,15 @@ struct ARMMemory { 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 @@ struct ARMCore { union PSR cpsr; union PSR spsr; - int32_t cyclesToEvent; + uint32_t cycles; + uint32_t nextEvent; int32_t bankedRegisters[6][7]; int32_t bankedSPSRs[6]; diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index 9d5218929..720da1aad 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -106,71 +106,85 @@ void ARMStep(struct ARMCore* cpu) { 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 @@ void ARMStep(struct ARMCore* cpu) { #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) \ diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index 7477e8f3f..23aba94ef 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -95,6 +95,7 @@ void ThumbStep(struct ARMCore* cpu) { #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) \ diff --git a/src/gba/gba-memory.c b/src/gba/gba-memory.c index b823fae9a..1dfa6daab 100644 --- a/src/gba/gba-memory.c +++ b/src/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 @@ void GBAMemoryInit(struct GBAMemory* 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 @@ void GBAMemoryDeinit(struct GBAMemory* memory) { 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; diff --git a/src/gba/gba-memory.h b/src/gba/gba-memory.h index 8351f6fc7..8132dc8d6 100644 --- a/src/gba/gba-memory.h +++ b/src/gba/gba-memory.h @@ -55,7 +55,8 @@ enum { }; enum { - OFFSET_MASK = 0x00FFFFFF + OFFSET_MASK = 0x00FFFFFF, + BASE_OFFSET = 24 }; struct GBAMemory { @@ -67,6 +68,11 @@ struct GBAMemory { 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);