Start implementing instruction timing

This commit is contained in:
Jeffrey Pfau 2013-04-14 23:12:03 -07:00
parent fa64310e83
commit ecc4775c31
6 changed files with 51 additions and 3 deletions

View File

@ -4,6 +4,8 @@
#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 @@ 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;

View File

@ -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];

View File

@ -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) \

View File

@ -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) \

View File

@ -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;

View File

@ -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);