mirror of https://github.com/mgba-emu/mgba.git
Load/Store multiple functions
This commit is contained in:
parent
4bb8b7b1fd
commit
537480b940
|
@ -48,6 +48,15 @@ enum RegisterBank {
|
|||
BANK_UNDEFINED = 5
|
||||
};
|
||||
|
||||
enum LSMDirection {
|
||||
LSM_B = 1,
|
||||
LSM_D = 2,
|
||||
LSM_IA = 0,
|
||||
LSM_IB = 1,
|
||||
LSM_DA = 2,
|
||||
LSM_DB = 3
|
||||
};
|
||||
|
||||
struct ARMCore;
|
||||
|
||||
union PSR {
|
||||
|
@ -89,6 +98,9 @@ struct ARMMemory {
|
|||
void (*store16)(struct ARMCore*, uint32_t address, int16_t value, int* cycleCounter);
|
||||
void (*store8)(struct ARMCore*, uint32_t address, int8_t value, int* cycleCounter);
|
||||
|
||||
uint32_t (*loadMultiple)(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);
|
||||
uint32_t (*storeMultiple)(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);
|
||||
|
||||
uint32_t* activeRegion;
|
||||
uint32_t activeMask;
|
||||
uint32_t activeSeqCycles32;
|
||||
|
@ -98,7 +110,6 @@ struct ARMMemory {
|
|||
uint32_t activeUncachedCycles32;
|
||||
uint32_t activeUncachedCycles16;
|
||||
void (*setActiveRegion)(struct ARMCore*, uint32_t address);
|
||||
int (*waitMultiple)(struct ARMCore*, uint32_t startAddress, int count);
|
||||
};
|
||||
|
||||
struct ARMInterruptHandler {
|
||||
|
|
|
@ -241,6 +241,8 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
|
|||
#define ADDR_MODE_3_INDEX(U_OP, M) ADDR_MODE_2_INDEX(U_OP, M)
|
||||
#define ADDR_MODE_3_WRITEBACK(ADDR) ADDR_MODE_2_WRITEBACK(ADDR)
|
||||
|
||||
#define ADDR_MODE_4_WRITEBACK cpu->gprs[rn] = address
|
||||
|
||||
#define ARM_LOAD_POST_BODY \
|
||||
++currentCycles; \
|
||||
if (rd == ARM_PC) { \
|
||||
|
@ -385,66 +387,35 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) {
|
|||
|
||||
#define ARM_MS_POST ARMSetPrivilegeMode(cpu, privilegeMode);
|
||||
|
||||
#define ADDR_MODE_4_DA uint32_t addr = cpu->gprs[rn]
|
||||
#define ADDR_MODE_4_IA uint32_t addr = cpu->gprs[rn]
|
||||
#define ADDR_MODE_4_DB uint32_t addr = cpu->gprs[rn] - 4
|
||||
#define ADDR_MODE_4_IB uint32_t addr = cpu->gprs[rn] + 4
|
||||
#define ADDR_MODE_4_DAW cpu->gprs[rn] = addr
|
||||
#define ADDR_MODE_4_IAW cpu->gprs[rn] = addr
|
||||
#define ADDR_MODE_4_DBW cpu->gprs[rn] = addr + 4
|
||||
#define ADDR_MODE_4_IBW cpu->gprs[rn] = addr - 4
|
||||
|
||||
#define ARM_M_INCREMENT(BODY) \
|
||||
for (m = rs, i = 0; m; m >>= 1, ++i) { \
|
||||
if (m & 1) { \
|
||||
BODY; \
|
||||
addr += 4; \
|
||||
total += 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define ARM_M_DECREMENT(BODY) \
|
||||
for (m = 0x8000, i = 15; m; m >>= 1, --i) { \
|
||||
if (rs & m) { \
|
||||
BODY; \
|
||||
addr -= 4; \
|
||||
total += 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, ADDRESS, WRITEBACK, LOOP, S_PRE, S_POST, BODY, POST_BODY) \
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME, LS, WRITEBACK, S_PRE, S_POST, DIRECTION, POST_BODY) \
|
||||
DEFINE_INSTRUCTION_ARM(NAME, \
|
||||
int rn = (opcode >> 16) & 0xF; \
|
||||
int rs = opcode & 0x0000FFFF; \
|
||||
int m; \
|
||||
int i; \
|
||||
int total = 0; \
|
||||
ADDRESS; \
|
||||
uint32_t address = cpu->gprs[rn]; \
|
||||
S_PRE; \
|
||||
LOOP(BODY); \
|
||||
address = cpu->memory. LS ## Multiple(cpu, address, rs, LSM_ ## DIRECTION, ¤tCycles); \
|
||||
S_POST; \
|
||||
currentCycles += cpu->memory.waitMultiple(cpu, addr, total); \
|
||||
POST_BODY; \
|
||||
WRITEBACK;)
|
||||
|
||||
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, ADDR_MODE_4_DA, , ARM_M_DECREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, ADDR_MODE_4_DA, ADDR_MODE_4_DAW, ARM_M_DECREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, ADDR_MODE_4_DB, , ARM_M_DECREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DBW, ADDR_MODE_4_DB, ADDR_MODE_4_DBW, ARM_M_DECREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IA, ADDR_MODE_4_IA, , ARM_M_INCREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, ADDR_MODE_4_IA, ADDR_MODE_4_IAW, ARM_M_INCREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, ADDR_MODE_4_IB, , ARM_M_INCREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, ADDR_MODE_4_IB, ADDR_MODE_4_IBW, ARM_M_INCREMENT, , , BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, ADDR_MODE_4_DA, , ARM_M_DECREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, ADDR_MODE_4_DA, ADDR_MODE_4_DAW, ARM_M_DECREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, ADDR_MODE_4_DB, , ARM_M_DECREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, ADDR_MODE_4_DB, ADDR_MODE_4_DBW, ARM_M_DECREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, ADDR_MODE_4_IA, , ARM_M_INCREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, ADDR_MODE_4_IA, ADDR_MODE_4_IAW, ARM_M_INCREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, ADDR_MODE_4_IB, , ARM_M_INCREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, ADDR_MODE_4_IB, ADDR_MODE_4_IBW, ARM_M_INCREMENT, ARM_MS_PRE, ARM_MS_POST, BODY, POST_BODY)
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(NAME, LS, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DA, LS, , , , DA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DAW, LS, ADDR_MODE_4_WRITEBACK, , , DA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DB, LS, , , , DB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## DBW, LS, ADDR_MODE_4_WRITEBACK, , , DB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IA, LS, , , , IA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IAW, LS, ADDR_MODE_4_WRITEBACK, , , IA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IB, LS, , , , IB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## IBW, LS, ADDR_MODE_4_WRITEBACK, , , IB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDA, LS, , ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDAW, LS, ADDR_MODE_4_WRITEBACK, ARM_MS_PRE, ARM_MS_POST, DA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDB, LS, , ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SDBW, LS, ADDR_MODE_4_WRITEBACK, ARM_MS_PRE, ARM_MS_POST, DB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIA, LS, , ARM_MS_PRE, ARM_MS_POST, IA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIAW, LS, ADDR_MODE_4_WRITEBACK, ARM_MS_PRE, ARM_MS_POST, IA, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIB, LS, , ARM_MS_PRE, ARM_MS_POST, IB, POST_BODY) \
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_EX_ARM(NAME ## SIBW, LS, ADDR_MODE_4_WRITEBACK, ARM_MS_PRE, ARM_MS_POST, IB, POST_BODY)
|
||||
|
||||
// Begin ALU definitions
|
||||
|
||||
|
@ -580,14 +551,14 @@ DEFINE_LOAD_STORE_T_INSTRUCTION_ARM(STRT,
|
|||
ARM_STORE_POST_BODY;)
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(LDM,
|
||||
cpu->gprs[i] = cpu->memory.load32(cpu, addr & 0xFFFFFFFC, 0);,
|
||||
load,
|
||||
++currentCycles;
|
||||
if (rs & 0x8000) {
|
||||
ARM_WRITE_PC;
|
||||
})
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_INSTRUCTION_ARM(STM,
|
||||
cpu->memory.store32(cpu, addr, cpu->gprs[i], 0);,
|
||||
store,
|
||||
currentCycles += cpu->memory.activeNonseqCycles32 - cpu->memory.activeSeqCycles32)
|
||||
|
||||
DEFINE_INSTRUCTION_ARM(SWP,
|
||||
|
|
|
@ -289,39 +289,30 @@ DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STR2, cpu->memory.store32(cpu, cpu->gprs[r
|
|||
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRB2, cpu->memory.store8(cpu, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], ¤tCycles); THUMB_STORE_POST_BODY;)
|
||||
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory.store16(cpu, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], ¤tCycles); THUMB_STORE_POST_BODY;)
|
||||
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, ADDRESS, LOOP, BODY, OP, PRE_BODY, POST_BODY, WRITEBACK) \
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(NAME, RN, LS, DIRECTION, PRE_BODY, WRITEBACK) \
|
||||
DEFINE_INSTRUCTION_THUMB(NAME, \
|
||||
int rn = RN; \
|
||||
UNUSED(rn); \
|
||||
int rs = opcode & 0xFF; \
|
||||
int32_t address = ADDRESS; \
|
||||
int m; \
|
||||
int i; \
|
||||
int total = 0; \
|
||||
int32_t address = cpu->gprs[RN]; \
|
||||
PRE_BODY; \
|
||||
for LOOP { \
|
||||
if (rs & m) { \
|
||||
BODY; \
|
||||
address OP 4; \
|
||||
++total; \
|
||||
} \
|
||||
} \
|
||||
POST_BODY; \
|
||||
currentCycles += cpu->memory.waitMultiple(cpu, address, total); \
|
||||
address = cpu->memory. LS ## Multiple(cpu, address, rs, LSM_ ## DIRECTION, ¤tCycles); \
|
||||
WRITEBACK;)
|
||||
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME, BODY, WRITEBACK) \
|
||||
COUNT_CALL_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## _R, cpu->gprs[rn], (m = 0x01, i = 0; i < 8; m <<= 1, ++i), BODY, +=, , , WRITEBACK)
|
||||
#define DEFINE_LOAD_STORE_MULTIPLE_THUMB(NAME, LS, DIRECTION, WRITEBACK) \
|
||||
COUNT_CALL_3(DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB, NAME ## _R, LS, DIRECTION, , WRITEBACK)
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_THUMB(LDMIA,
|
||||
cpu->gprs[i] = cpu->memory.load32(cpu, address, 0),
|
||||
load,
|
||||
IA,
|
||||
THUMB_LOAD_POST_BODY;
|
||||
if (!((1 << rn) & rs)) {
|
||||
cpu->gprs[rn] = address;
|
||||
})
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_THUMB(STMIA,
|
||||
cpu->memory.store32(cpu, address, cpu->gprs[i], 0),
|
||||
store,
|
||||
IA,
|
||||
THUMB_STORE_POST_BODY;
|
||||
cpu->gprs[rn] = address;)
|
||||
|
||||
|
@ -352,48 +343,37 @@ DEFINE_INSTRUCTION_THUMB(ADD7, cpu->gprs[ARM_SP] += (opcode & 0x7F) << 2)
|
|||
DEFINE_INSTRUCTION_THUMB(SUB4, cpu->gprs[ARM_SP] -= (opcode & 0x7F) << 2)
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POP,
|
||||
opcode & 0x00FF,
|
||||
cpu->gprs[ARM_SP],
|
||||
(m = 0x01, i = 0; i < 8; m <<= 1, ++i),
|
||||
cpu->gprs[i] = cpu->memory.load32(cpu, address, 0),
|
||||
+=,
|
||||
ARM_SP,
|
||||
load,
|
||||
IA,
|
||||
,
|
||||
THUMB_LOAD_POST_BODY;,
|
||||
THUMB_LOAD_POST_BODY;
|
||||
cpu->gprs[ARM_SP] = address)
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(POPR,
|
||||
opcode & 0x00FF,
|
||||
cpu->gprs[ARM_SP],
|
||||
(m = 0x01, i = 0; i < 8; m <<= 1, ++i),
|
||||
cpu->gprs[i] = cpu->memory.load32(cpu, address, 0),
|
||||
+=,
|
||||
,
|
||||
cpu->gprs[ARM_PC] = cpu->memory.load32(cpu, address, 0) & 0xFFFFFFFE;
|
||||
address += 4;
|
||||
THUMB_LOAD_POST_BODY;,
|
||||
ARM_SP,
|
||||
load,
|
||||
IA,
|
||||
rs |= 1 << ARM_PC,
|
||||
THUMB_LOAD_POST_BODY;
|
||||
cpu->gprs[ARM_SP] = address;
|
||||
THUMB_WRITE_PC;)
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSH,
|
||||
opcode & 0x00FF,
|
||||
cpu->gprs[ARM_SP] - 4,
|
||||
(m = 0x80, i = 7; m; m >>= 1, --i),
|
||||
cpu->memory.store32(cpu, address, cpu->gprs[i], 0),
|
||||
-=,
|
||||
ARM_SP,
|
||||
store,
|
||||
DB,
|
||||
,
|
||||
THUMB_STORE_POST_BODY,
|
||||
cpu->gprs[ARM_SP] = address + 4)
|
||||
THUMB_STORE_POST_BODY;
|
||||
cpu->gprs[ARM_SP] = address)
|
||||
|
||||
DEFINE_LOAD_STORE_MULTIPLE_EX_THUMB(PUSHR,
|
||||
opcode & 0x00FF,
|
||||
cpu->gprs[ARM_SP] - 4,
|
||||
(m = 0x80, i = 7; m; m >>= 1, --i),
|
||||
cpu->memory.store32(cpu, address, cpu->gprs[i], 0),
|
||||
-=,
|
||||
cpu->memory.store32(cpu, address, cpu->gprs[ARM_LR], 0);
|
||||
address -= 4;,
|
||||
THUMB_STORE_POST_BODY,
|
||||
cpu->gprs[ARM_SP] = address + 4)
|
||||
ARM_SP,
|
||||
store,
|
||||
DB,
|
||||
rs |= 1 << ARM_LR,
|
||||
THUMB_STORE_POST_BODY;
|
||||
cpu->gprs[ARM_SP] = address)
|
||||
|
||||
DEFINE_INSTRUCTION_THUMB(ILL, ARM_ILL)
|
||||
DEFINE_INSTRUCTION_THUMB(BKPT, ARM_STUB)
|
||||
|
|
|
@ -43,7 +43,6 @@ CREATE_WATCHPOINT_SHIM(loadU8, 1, uint8_t, (struct ARMCore* cpu, uint32_t addres
|
|||
CREATE_WATCHPOINT_SHIM(store32, 4, void, (struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter), address, value, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(store16, 2, void, (struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter), address, value, cycleCounter)
|
||||
CREATE_WATCHPOINT_SHIM(store8, 1, void, (struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter), address, value, cycleCounter)
|
||||
CREATE_SHIM(waitMultiple, int, (struct ARMCore* cpu, uint32_t startAddress, int count), startAddress, count)
|
||||
CREATE_SHIM(setActiveRegion, void, (struct ARMCore* cpu, uint32_t address), address)
|
||||
|
||||
static bool _checkWatchpoints(struct DebugBreakpoint* watchpoints, uint32_t address, int width) {
|
||||
|
@ -67,7 +66,6 @@ void ARMDebuggerInstallMemoryShim(struct ARMDebugger* debugger) {
|
|||
debugger->cpu->memory.load8 = ARMDebuggerShim_load8;
|
||||
debugger->cpu->memory.loadU8 = ARMDebuggerShim_loadU8;
|
||||
debugger->cpu->memory.setActiveRegion = ARMDebuggerShim_setActiveRegion;
|
||||
debugger->cpu->memory.waitMultiple = ARMDebuggerShim_waitMultiple;
|
||||
}
|
||||
|
||||
void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
|
||||
|
@ -80,5 +78,4 @@ void ARMDebuggerRemoveMemoryShim(struct ARMDebugger* debugger) {
|
|||
debugger->cpu->memory.load8 = debugger->originalMemory.load8;
|
||||
debugger->cpu->memory.loadU8 = debugger->originalMemory.loadU8;
|
||||
debugger->cpu->memory.setActiveRegion = debugger->originalMemory.setActiveRegion;
|
||||
debugger->cpu->memory.waitMultiple = debugger->originalMemory.waitMultiple;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#include "util/memory.h"
|
||||
|
||||
static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t region);
|
||||
static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count);
|
||||
static void GBAMemoryServiceDMA(struct GBA* gba, int number, struct GBADMA* info);
|
||||
|
||||
static const char GBA_BASE_WAITSTATES[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 4 };
|
||||
|
@ -27,9 +26,11 @@ void GBAMemoryInit(struct GBA* gba) {
|
|||
cpu->memory.loadU16 = GBALoadU16;
|
||||
cpu->memory.load8 = GBALoad8;
|
||||
cpu->memory.loadU8 = GBALoadU8;
|
||||
cpu->memory.loadMultiple = GBALoadMultiple;
|
||||
cpu->memory.store32 = GBAStore32;
|
||||
cpu->memory.store16 = GBAStore16;
|
||||
cpu->memory.store8 = GBAStore8;
|
||||
cpu->memory.storeMultiple = GBAStoreMultiple;
|
||||
|
||||
gba->memory.bios = (uint32_t*) hleBios;
|
||||
gba->memory.fullBios = 0;
|
||||
|
@ -67,7 +68,6 @@ void GBAMemoryInit(struct GBA* gba) {
|
|||
cpu->memory.activeUncachedCycles32 = 0;
|
||||
cpu->memory.activeUncachedCycles16 = 0;
|
||||
gba->memory.biosPrefetch = 0;
|
||||
cpu->memory.waitMultiple = GBAWaitMultiple;
|
||||
}
|
||||
|
||||
void GBAMemoryDeinit(struct GBA* gba) {
|
||||
|
@ -558,12 +558,203 @@ void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCo
|
|||
}
|
||||
}
|
||||
|
||||
static int GBAWaitMultiple(struct ARMCore* cpu, uint32_t startAddress, int count) {
|
||||
uint32_t GBALoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
|
||||
struct GBA* gba = (struct GBA*) cpu->master;
|
||||
struct GBAMemory* memory = &gba->memory;
|
||||
int wait = 1 + memory->waitstatesNonseq32[startAddress >> BASE_OFFSET];
|
||||
wait += (1 + memory->waitstatesSeq32[startAddress >> BASE_OFFSET]) * (count - 1);
|
||||
return wait;
|
||||
uint32_t value;
|
||||
int wait;
|
||||
int totalWait = 0;
|
||||
char* waitstatesRegion = memory->waitstatesNonseq32;
|
||||
|
||||
int i;
|
||||
int offset = 4;
|
||||
int popcount = 0;
|
||||
if (direction & LSM_D) {
|
||||
offset = -4;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
if (mask & (1 << i)) {
|
||||
++popcount;
|
||||
}
|
||||
}
|
||||
address -= (popcount << 2) - 4;
|
||||
}
|
||||
|
||||
if (direction & LSM_B) {
|
||||
address += offset;
|
||||
}
|
||||
|
||||
address &= 0xFFFFFFFC;
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
wait = 0;
|
||||
if (~mask & (1 << i)) {
|
||||
continue;
|
||||
}
|
||||
switch (address >> BASE_OFFSET) {
|
||||
case REGION_BIOS:
|
||||
if (memory->activeRegion == REGION_BIOS) {
|
||||
if (address < SIZE_BIOS) {
|
||||
LOAD_32(value, address, memory->bios);
|
||||
} else {
|
||||
value = 0;
|
||||
}
|
||||
} else {
|
||||
value = memory->biosPrefetch;
|
||||
}
|
||||
break;
|
||||
case REGION_WORKING_RAM:
|
||||
LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
|
||||
wait = waitstatesRegion[REGION_WORKING_RAM];
|
||||
break;
|
||||
case REGION_WORKING_IRAM:
|
||||
LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
|
||||
break;
|
||||
case REGION_IO:
|
||||
value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16);
|
||||
break;
|
||||
case REGION_PALETTE_RAM:
|
||||
LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
|
||||
break;
|
||||
case REGION_VRAM:
|
||||
LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
|
||||
break;
|
||||
case REGION_OAM:
|
||||
LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
|
||||
break;
|
||||
case REGION_CART0:
|
||||
case REGION_CART0_EX:
|
||||
case REGION_CART1:
|
||||
case REGION_CART1_EX:
|
||||
case REGION_CART2:
|
||||
case REGION_CART2_EX:
|
||||
wait = waitstatesRegion[address >> BASE_OFFSET];
|
||||
if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
|
||||
LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom);
|
||||
}
|
||||
break;
|
||||
case REGION_CART_SRAM:
|
||||
case REGION_CART_SRAM_MIRROR:
|
||||
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Load32: 0x%08X", address);
|
||||
break;
|
||||
default:
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
|
||||
value = cpu->prefetch;
|
||||
if (cpu->executionMode == MODE_THUMB) {
|
||||
value |= value << 16;
|
||||
}
|
||||
break;
|
||||
}
|
||||
waitstatesRegion = memory->waitstatesSeq32;
|
||||
cpu->gprs[i] = value;
|
||||
totalWait += 1 + wait;
|
||||
address += 4;
|
||||
}
|
||||
|
||||
if (cycleCounter) {
|
||||
*cycleCounter += totalWait;
|
||||
}
|
||||
|
||||
if (direction & LSM_B) {
|
||||
address -= offset;
|
||||
}
|
||||
|
||||
if (direction & LSM_D) {
|
||||
address -= (popcount << 2) + 4;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32_t GBAStoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
|
||||
struct GBA* gba = (struct GBA*) cpu->master;
|
||||
struct GBAMemory* memory = &gba->memory;
|
||||
uint32_t value;
|
||||
int wait;
|
||||
int totalWait = 0;
|
||||
char* waitstatesRegion = memory->waitstatesNonseq32;
|
||||
|
||||
int i;
|
||||
int offset = 4;
|
||||
int popcount = 0;
|
||||
if (direction & LSM_D) {
|
||||
offset = -4;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
if (mask & (1 << i)) {
|
||||
++popcount;
|
||||
}
|
||||
}
|
||||
address -= (popcount << 2) - 4;
|
||||
}
|
||||
|
||||
if (direction & LSM_B) {
|
||||
address += offset;
|
||||
}
|
||||
|
||||
address &= 0xFFFFFFFC;
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
wait = 0;
|
||||
if (~mask & (1 << i)) {
|
||||
continue;
|
||||
}
|
||||
value = cpu->gprs[i];
|
||||
switch (address >> BASE_OFFSET) {
|
||||
case REGION_WORKING_RAM:
|
||||
STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram);
|
||||
wait = waitstatesRegion[REGION_WORKING_RAM];
|
||||
break;
|
||||
case REGION_WORKING_IRAM:
|
||||
STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram);
|
||||
break;
|
||||
case REGION_IO:
|
||||
GBAIOWrite32(gba, address & (SIZE_IO - 1), value);
|
||||
break;
|
||||
case REGION_PALETTE_RAM:
|
||||
STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette);
|
||||
gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16);
|
||||
gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value);
|
||||
break;
|
||||
case REGION_VRAM:
|
||||
if ((address & OFFSET_MASK) < SIZE_VRAM) {
|
||||
STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram);
|
||||
} else if ((address & OFFSET_MASK) < 0x00020000) {
|
||||
STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram);
|
||||
}
|
||||
break;
|
||||
case REGION_OAM:
|
||||
STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw);
|
||||
gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1);
|
||||
gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1);
|
||||
break;
|
||||
case REGION_CART0:
|
||||
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
|
||||
break;
|
||||
case REGION_CART_SRAM:
|
||||
case REGION_CART_SRAM_MIRROR:
|
||||
GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Store32: 0x%08X", address);
|
||||
break;
|
||||
default:
|
||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Store32: 0x%08X", address);
|
||||
break;
|
||||
}
|
||||
waitstatesRegion = memory->waitstatesSeq32;
|
||||
totalWait += 1 + wait;
|
||||
address += 4;
|
||||
}
|
||||
|
||||
if (cycleCounter) {
|
||||
*cycleCounter += totalWait;
|
||||
}
|
||||
|
||||
if (direction & LSM_B) {
|
||||
address -= offset;
|
||||
}
|
||||
|
||||
if (direction & LSM_D) {
|
||||
address -= (popcount << 2) + 4;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters) {
|
||||
|
|
|
@ -149,6 +149,9 @@ void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycle
|
|||
void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter);
|
||||
void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter);
|
||||
|
||||
uint32_t GBALoadMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);
|
||||
uint32_t GBAStoreMultiple(struct ARMCore*, uint32_t baseAddress, int mask, enum LSMDirection direction, int* cycleCounter);
|
||||
|
||||
void GBAAdjustWaitstates(struct GBA* gba, uint16_t parameters);
|
||||
|
||||
void GBAMemoryWriteDMASAD(struct GBA* gba, int dma, uint32_t address);
|
||||
|
|
Loading…
Reference in New Issue