Load/Store multiple functions

This commit is contained in:
Jeffrey Pfau 2014-10-21 03:53:48 -07:00
parent 4bb8b7b1fd
commit 537480b940
6 changed files with 265 additions and 112 deletions

View File

@ -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 {

View File

@ -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, &currentCycles); \
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,

View File

@ -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], &currentCycles); THUMB_STORE_POST_BODY;)
DEFINE_LOAD_STORE_WITH_REGISTER_THUMB(STRH2, cpu->memory.store16(cpu, cpu->gprs[rn] + cpu->gprs[rm], cpu->gprs[rd], &currentCycles); 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, &currentCycles); \
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)

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);