Reimplement prefetch, temporarily removing busy loop optimization

This commit is contained in:
Jeffrey Pfau 2014-08-28 05:45:37 -07:00
parent ca3e1c428e
commit baa71027e3
4 changed files with 28 additions and 29 deletions

View File

@ -117,7 +117,6 @@ void ARMReset(struct ARMCore* cpu) {
cpu->executionMode = MODE_THUMB; cpu->executionMode = MODE_THUMB;
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->currentPC = 0;
int currentCycles = 0; int currentCycles = 0;
ARM_WRITE_PC; ARM_WRITE_PC;
@ -142,7 +141,9 @@ void ARMRaiseIRQ(struct ARMCore* cpu) {
ARMSetPrivilegeMode(cpu, MODE_IRQ); ARMSetPrivilegeMode(cpu, MODE_IRQ);
cpu->cpsr.priv = MODE_IRQ; cpu->cpsr.priv = MODE_IRQ;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth + WORD_SIZE_ARM; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth + WORD_SIZE_ARM;
cpu->gprs[ARM_PC] = BASE_IRQ + WORD_SIZE_ARM; cpu->gprs[ARM_PC] = BASE_IRQ;
int currentCycles = 0;
ARM_WRITE_PC;
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]);
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
@ -160,7 +161,9 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR); ARMSetPrivilegeMode(cpu, MODE_SUPERVISOR);
cpu->cpsr.priv = MODE_SUPERVISOR; cpu->cpsr.priv = MODE_SUPERVISOR;
cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth; cpu->gprs[ARM_LR] = cpu->gprs[ARM_PC] - instructionWidth;
cpu->gprs[ARM_PC] = BASE_SWI + WORD_SIZE_ARM; cpu->gprs[ARM_PC] = BASE_SWI;
int currentCycles = 0;
ARM_WRITE_PC;
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]);
_ARMSetMode(cpu, MODE_ARM); _ARMSetMode(cpu, MODE_ARM);
cpu->spsr = cpsr; cpu->spsr = cpsr;
@ -168,12 +171,11 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
} }
static inline void ARMStep(struct ARMCore* cpu) { static inline void ARMStep(struct ARMCore* cpu) {
uint32_t opcode; uint32_t opcode = cpu->prefetch;
cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_ARM; LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
LOAD_32(opcode, cpu->currentPC & cpu->memory.activeMask, cpu->memory.activeRegion);
cpu->gprs[ARM_PC] += WORD_SIZE_ARM; cpu->gprs[ARM_PC] += WORD_SIZE_ARM;
int condition = opcode >> 28; unsigned condition = opcode >> 28;
if (condition == 0xE) { if (condition == 0xE) {
ARMInstruction instruction = _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)]; ARMInstruction instruction = _armTable[((opcode >> 16) & 0xFF0) | ((opcode >> 4) & 0x00F)];
instruction(cpu, opcode); instruction(cpu, opcode);
@ -273,10 +275,9 @@ static inline void ARMStep(struct ARMCore* cpu) {
} }
static inline void ThumbStep(struct ARMCore* cpu) { static inline void ThumbStep(struct ARMCore* cpu) {
cpu->currentPC = cpu->gprs[ARM_PC] - WORD_SIZE_THUMB; uint32_t opcode = cpu->prefetch;
LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
uint16_t opcode;
LOAD_16(opcode, cpu->currentPC & cpu->memory.activeMask, cpu->memory.activeRegion);
ThumbInstruction instruction = _thumbTable[opcode >> 6]; ThumbInstruction instruction = _thumbTable[opcode >> 6];
instruction(cpu, opcode); instruction(cpu, opcode);
} }

View File

@ -133,7 +133,7 @@ struct ARMCore {
int32_t shifterOperand; int32_t shifterOperand;
int32_t shifterCarryOut; int32_t shifterCarryOut;
uint32_t currentPC; uint32_t prefetch;
enum ExecutionMode executionMode; enum ExecutionMode executionMode;
enum PrivilegeMode privilegeMode; enum PrivilegeMode privilegeMode;

View File

@ -44,13 +44,17 @@
#define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode) #define ARM_ILL cpu->irqh.hitIllegal(cpu, opcode)
#define ARM_WRITE_PC \ #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); \
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC] - WORD_SIZE_ARM); \ cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \
LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
cpu->gprs[ARM_PC] += WORD_SIZE_ARM; \
currentCycles += 2 + cpu->memory.activeUncachedCycles32 + cpu->memory.activeSeqCycles32; currentCycles += 2 + cpu->memory.activeUncachedCycles32 + cpu->memory.activeSeqCycles32;
#define THUMB_WRITE_PC \ #define THUMB_WRITE_PC \
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB) + WORD_SIZE_THUMB; \ cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB); \
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC] - WORD_SIZE_THUMB); \ cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \
LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; \
currentCycles += 2 + cpu->memory.activeUncachedCycles16 + cpu->memory.activeSeqCycles16; currentCycles += 2 + cpu->memory.activeUncachedCycles16 + cpu->memory.activeSeqCycles16;
static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) { static inline int _ARMModeHasSPSR(enum PrivilegeMode mode) {

View File

@ -109,16 +109,12 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
struct GBA* gba = (struct GBA*) cpu->master; struct GBA* gba = (struct GBA*) cpu->master;
struct GBAMemory* memory = &gba->memory; struct GBAMemory* memory = &gba->memory;
if (cpu->currentPC == gba->busyLoop) {
GBAHalt(gba);
}
int newRegion = address >> BASE_OFFSET; int newRegion = address >> BASE_OFFSET;
if (newRegion == memory->activeRegion) { if (newRegion == memory->activeRegion) {
return; return;
} }
if (memory->activeRegion == REGION_BIOS) { if (memory->activeRegion == REGION_BIOS) {
memory->biosPrefetch = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); memory->biosPrefetch = cpu->prefetch;
} }
memory->activeRegion = newRegion; memory->activeRegion = newRegion;
switch (address & ~OFFSET_MASK) { switch (address & ~OFFSET_MASK) {
@ -165,7 +161,7 @@ int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
switch (address & ~OFFSET_MASK) { switch (address & ~OFFSET_MASK) {
case BASE_BIOS: case BASE_BIOS:
if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) { if (cpu->gprs[ARM_PC] >> BASE_OFFSET == REGION_BIOS) {
if (address < SIZE_BIOS) { if (address < SIZE_BIOS) {
LOAD_32(value, address, memory->bios); LOAD_32(value, address, memory->bios);
} else { } else {
@ -211,10 +207,8 @@ int32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
break; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
if (cpu->executionMode == MODE_ARM) { value = cpu->prefetch;
value = cpu->memory.load32(cpu, cpu->currentPC + WORD_SIZE_ARM * 2, 0); if (cpu->executionMode == MODE_THUMB) {
} else {
value = cpu->memory.load16(cpu, cpu->currentPC + WORD_SIZE_THUMB * 2, 0);
value |= value << 16; value |= value << 16;
} }
break; break;
@ -241,7 +235,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
switch (address & ~OFFSET_MASK) { switch (address & ~OFFSET_MASK) {
case BASE_BIOS: case BASE_BIOS:
if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) { if (cpu->gprs[ARM_PC] >> BASE_OFFSET == REGION_BIOS) {
if (address < SIZE_BIOS) { if (address < SIZE_BIOS) {
LOAD_16(value, address, memory->bios); LOAD_16(value, address, memory->bios);
} else { } else {
@ -294,7 +288,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
break; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0); value = cpu->prefetch;
break; break;
} }
@ -318,7 +312,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
switch (address & ~OFFSET_MASK) { switch (address & ~OFFSET_MASK) {
case BASE_BIOS: case BASE_BIOS:
if (cpu->currentPC >> BASE_OFFSET == REGION_BIOS) { if (cpu->gprs[ARM_PC] >> BASE_OFFSET == REGION_BIOS) {
if (address < SIZE_BIOS) { if (address < SIZE_BIOS) {
value = ((int8_t*) memory->bios)[address]; value = ((int8_t*) memory->bios)[address];
} else { } else {
@ -372,7 +366,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
break; break;
default: default:
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address); GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
value = cpu->memory.load16(cpu, cpu->currentPC + (cpu->executionMode == MODE_ARM ? WORD_SIZE_ARM : WORD_SIZE_THUMB) * 2, 0) >> ((address & 1) << 3); value = cpu->prefetch & 0xFF;
break; break;
} }