mirror of https://github.com/mgba-emu/mgba.git
ARM7: Extend prefetch by one stage
This commit is contained in:
parent
f57b47b3f2
commit
28ac288d2c
1
CHANGES
1
CHANGES
|
@ -10,6 +10,7 @@ Bugfixes:
|
||||||
- GBA BIOS: Fix HLE Lz77 and RL functions to properly account for width and invalid addresses
|
- GBA BIOS: Fix HLE Lz77 and RL functions to properly account for width and invalid addresses
|
||||||
- ARM7: Fix LDM writeback to a register already written
|
- ARM7: Fix LDM writeback to a register already written
|
||||||
- GBA Memory: Don't call into GPIO write calls if GPIO devices are absent
|
- GBA Memory: Don't call into GPIO write calls if GPIO devices are absent
|
||||||
|
- ARM7: Extend prefetch by one stage
|
||||||
Misc:
|
Misc:
|
||||||
- Qt: Disable sync to video by default
|
- Qt: Disable sync to video by default
|
||||||
- GBA: Exit cleanly on FATAL if the port supports it
|
- GBA: Exit cleanly on FATAL if the port supports it
|
||||||
|
|
|
@ -176,9 +176,10 @@ void ARMRaiseSWI(struct ARMCore* cpu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ARMStep(struct ARMCore* cpu) {
|
static inline void ARMStep(struct ARMCore* cpu) {
|
||||||
uint32_t opcode = cpu->prefetch;
|
uint32_t opcode = cpu->prefetch[0];
|
||||||
LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
|
cpu->prefetch[0] = cpu->prefetch[1];
|
||||||
cpu->gprs[ARM_PC] += WORD_SIZE_ARM;
|
cpu->gprs[ARM_PC] += WORD_SIZE_ARM;
|
||||||
|
LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
|
||||||
|
|
||||||
unsigned condition = opcode >> 28;
|
unsigned condition = opcode >> 28;
|
||||||
if (condition != 0xE) {
|
if (condition != 0xE) {
|
||||||
|
@ -239,9 +240,10 @@ static inline void ARMStep(struct ARMCore* cpu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void ThumbStep(struct ARMCore* cpu) {
|
static inline void ThumbStep(struct ARMCore* cpu) {
|
||||||
uint32_t opcode = cpu->prefetch;
|
uint32_t opcode = cpu->prefetch[0];
|
||||||
LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
|
cpu->prefetch[0] = cpu->prefetch[1];
|
||||||
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
|
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB;
|
||||||
|
LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion);
|
||||||
ThumbInstruction instruction = _thumbTable[opcode >> 6];
|
ThumbInstruction instruction = _thumbTable[opcode >> 6];
|
||||||
instruction(cpu, opcode);
|
instruction(cpu, opcode);
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ struct ARMCore {
|
||||||
int32_t shifterOperand;
|
int32_t shifterOperand;
|
||||||
int32_t shifterCarryOut;
|
int32_t shifterCarryOut;
|
||||||
|
|
||||||
uint32_t prefetch;
|
uint32_t prefetch[2];
|
||||||
enum ExecutionMode executionMode;
|
enum ExecutionMode executionMode;
|
||||||
enum PrivilegeMode privilegeMode;
|
enum PrivilegeMode privilegeMode;
|
||||||
|
|
||||||
|
|
|
@ -52,15 +52,17 @@
|
||||||
#define ARM_WRITE_PC \
|
#define ARM_WRITE_PC \
|
||||||
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM); \
|
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_ARM); \
|
||||||
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \
|
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \
|
||||||
LOAD_32(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
|
LOAD_32(cpu->prefetch[0], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
|
||||||
cpu->gprs[ARM_PC] += WORD_SIZE_ARM; \
|
cpu->gprs[ARM_PC] += WORD_SIZE_ARM; \
|
||||||
|
LOAD_32(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
|
||||||
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); \
|
cpu->gprs[ARM_PC] = (cpu->gprs[ARM_PC] & -WORD_SIZE_THUMB); \
|
||||||
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \
|
cpu->memory.setActiveRegion(cpu, cpu->gprs[ARM_PC]); \
|
||||||
LOAD_16(cpu->prefetch, cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
|
LOAD_16(cpu->prefetch[0], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
|
||||||
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; \
|
cpu->gprs[ARM_PC] += WORD_SIZE_THUMB; \
|
||||||
|
LOAD_16(cpu->prefetch[1], cpu->gprs[ARM_PC] & cpu->memory.activeMask, cpu->memory.activeRegion); \
|
||||||
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) {
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
|
||||||
static uint32_t _popcount32(unsigned bits);
|
static uint32_t _popcount32(unsigned bits);
|
||||||
static uint32_t _deadbeef = 0xDEADBEEF;
|
static uint32_t _deadbeef[2] = { 0xDEADBEEF, 0xFEEDFACE };
|
||||||
|
|
||||||
static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
|
static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
|
||||||
static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
|
static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
|
||||||
|
@ -128,7 +128,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (memory->activeRegion == REGION_BIOS) {
|
if (memory->activeRegion == REGION_BIOS) {
|
||||||
memory->biosPrefetch = cpu->prefetch;
|
memory->biosPrefetch = cpu->prefetch[0];
|
||||||
}
|
}
|
||||||
memory->activeRegion = newRegion;
|
memory->activeRegion = newRegion;
|
||||||
switch (address & ~OFFSET_MASK) {
|
switch (address & ~OFFSET_MASK) {
|
||||||
|
@ -158,7 +158,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
cpu->memory.activeMask = SIZE_CART0 - 1;
|
cpu->memory.activeMask = SIZE_CART0 - 1;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cpu->memory.activeRegion = &_deadbeef;
|
cpu->memory.activeRegion = _deadbeef;
|
||||||
cpu->memory.activeMask = 0;
|
cpu->memory.activeMask = 0;
|
||||||
GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
|
GBALog(gba, GBA_LOG_FATAL, "Jumped to invalid address");
|
||||||
break;
|
break;
|
||||||
|
@ -176,7 +176,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
if (cpu->cycles >= cpu->nextEvent) { \
|
if (cpu->cycles >= cpu->nextEvent) { \
|
||||||
value = gba->bus; \
|
value = gba->bus; \
|
||||||
} else { \
|
} else { \
|
||||||
value = cpu->prefetch; \
|
value = cpu->prefetch[0]; \
|
||||||
if (cpu->executionMode == MODE_THUMB) { \
|
if (cpu->executionMode == MODE_THUMB) { \
|
||||||
value |= value << 16; \
|
value |= value << 16; \
|
||||||
} \
|
} \
|
||||||
|
@ -303,7 +303,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
value = gba->bus;
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch;
|
value = cpu->prefetch[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -359,7 +359,7 @@ int16_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
value = gba->bus;
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch;
|
value = cpu->prefetch[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -396,7 +396,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
value = gba->bus;
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch;
|
value = cpu->prefetch[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -454,7 +454,7 @@ int8_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
if (cpu->cycles >= cpu->nextEvent) {
|
if (cpu->cycles >= cpu->nextEvent) {
|
||||||
value = gba->bus;
|
value = gba->bus;
|
||||||
} else {
|
} else {
|
||||||
value = cpu->prefetch;
|
value = cpu->prefetch[0];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,10 +82,12 @@ void GBADeserialize(struct GBA* gba, struct GBASerializedState* state) {
|
||||||
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
gba->cpu->memory.setActiveRegion(gba->cpu, gba->cpu->gprs[ARM_PC]);
|
||||||
if (gba->cpu->cpsr.t) {
|
if (gba->cpu->cpsr.t) {
|
||||||
gba->cpu->executionMode = MODE_THUMB;
|
gba->cpu->executionMode = MODE_THUMB;
|
||||||
LOAD_16(gba->cpu->prefetch, (gba->cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
LOAD_16(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_THUMB) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||||
|
LOAD_16(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||||
} else {
|
} else {
|
||||||
gba->cpu->executionMode = MODE_ARM;
|
gba->cpu->executionMode = MODE_ARM;
|
||||||
LOAD_32(gba->cpu->prefetch, (gba->cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
LOAD_32(gba->cpu->prefetch[0], (gba->cpu->gprs[ARM_PC] - WORD_SIZE_ARM) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||||
|
LOAD_32(gba->cpu->prefetch[1], (gba->cpu->gprs[ARM_PC]) & gba->cpu->memory.activeMask, gba->cpu->memory.activeRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
GBAMemoryDeserialize(&gba->memory, state);
|
GBAMemoryDeserialize(&gba->memory, state);
|
||||||
|
|
|
@ -227,9 +227,9 @@ static void GBAProcessEvents(struct ARMCore* cpu) {
|
||||||
int32_t nextEvent = INT_MAX;
|
int32_t nextEvent = INT_MAX;
|
||||||
int32_t testEvent;
|
int32_t testEvent;
|
||||||
|
|
||||||
gba->bus = cpu->prefetch;
|
gba->bus = cpu->prefetch[0];
|
||||||
if (cpu->executionMode == MODE_THUMB) {
|
if (cpu->executionMode == MODE_THUMB) {
|
||||||
gba->bus |= cpu->prefetch << 16;
|
gba->bus |= cpu->prefetch[0] << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gba->springIRQ) {
|
if (gba->springIRQ) {
|
||||||
|
|
Loading…
Reference in New Issue