mirror of https://github.com/mgba-emu/mgba.git
Reimplement prefetch, temporarily removing busy loop optimization
This commit is contained in:
parent
ca3e1c428e
commit
baa71027e3
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue