mirror of https://github.com/mgba-emu/mgba.git
Start implementing instruction timing
This commit is contained in:
parent
fa64310e83
commit
ecc4775c31
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue