DS Memory: Improve TCM handling
Vicki Pfau vi@endrift.com
Mon, 30 Jan 2017 18:33:19 -0800
3 files changed,
59 insertions(+),
21 deletions(-)
M
include/mgba/internal/ds/memory.h
→
include/mgba/internal/ds/memory.h
@@ -84,6 +84,10 @@
size_t romSize; size_t wramSize7; size_t wramSize9; + + uint32_t dtcmBase; + uint32_t dtcmSize; + uint32_t itcmSize; }; struct DSCoreMemory {
M
src/ds/ds.c
→
src/ds/ds.c
@@ -526,13 +526,17 @@
static void _writeTCMControl(struct ARMCore* cpu, int crm, int opcode2, uint32_t value) { uint32_t base = ARMTCMControlGetBase(value) << 12; uint32_t size = 512 << ARMTCMControlGetVirtualSize(value); + struct DS* ds = (struct DS*) cpu->master; mLOG(DS, DEBUG, "CP15 TCM control write: CRm: %i, Op2: %i, Base: %08X, Size: %08X", crm, opcode2, base, size); switch (opcode2) { case 0: cpu->cp15.r9.d = value; + ds->memory.dtcmBase = base; + ds->memory.dtcmSize = size; break; case 1: cpu->cp15.r9.i = value; + ds->memory.itcmSize = size; break; default: mLOG(DS, GAME_ERROR, "CP15 TCM control bad op2: %i", opcode2);
M
src/ds/memory.c
→
src/ds/memory.c
@@ -624,7 +624,7 @@ memory->activeRegion = newRegion;
switch (newRegion) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < ds->memory.itcmSize) { cpu->memory.activeRegion = ds->memory.itcm; cpu->memory.activeMask = DS9_SIZE_ITCM - 1; break;@@ -670,14 +670,14 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < memory->itcmSize) { LOAD_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm); break; } mLOG(DS_MEM, STUB, "Bad DS9 Load32: %08X:%08X", address, value); break; case DS_REGION_RAM: - if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); break; }@@ -696,6 +696,10 @@ // TODO: Fix masking
LOAD_32(value, address & (DS9_SIZE_BIOS - 1), memory->bios9); break; default: + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); + break; + } mLOG(DS_MEM, STUB, "Unimplemented DS9 Load32: %08X", address); break; }@@ -718,14 +722,14 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < memory->itcmSize) { LOAD_16(value, address & (DS9_SIZE_ITCM - 1), memory->itcm); break; } mLOG(DS_MEM, STUB, "Bad DS9 Load16: %08X:%08X", address, value); break; case DS_REGION_RAM: - if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { LOAD_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); break; }@@ -743,6 +747,10 @@ // TODO: Fix masking
LOAD_16(value, address & (DS9_SIZE_BIOS - 1), memory->bios9); break; default: + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + LOAD_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); + break; + } mLOG(DS_MEM, STUB, "Unimplemented DS9 Load16: %08X", address); break; }@@ -765,15 +773,15 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < memory->itcmSize) { value = ((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)]; break; } mLOG(DS_MEM, STUB, "Bad DS9 Load8: %08X:%08X", address, value); break; case DS_REGION_RAM: - if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { - value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)]; + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM- 1)]; break; } if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {@@ -787,6 +795,10 @@ // TODO: Fix masking
value = ((uint8_t*) memory->bios9)[address & (DS9_SIZE_BIOS - 1)]; break; default: + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)]; + break; + } mLOG(DS_MEM, STUB, "Unimplemented DS9 Load8: %08X", address); break; }@@ -806,14 +818,14 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < memory->itcmSize) { STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm); break; } mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value); break; case DS_REGION_RAM: - if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); break; }@@ -827,6 +839,10 @@ case DS_REGION_IO:
DS9IOWrite32(ds, address & 0x00FFFFFF, value); break; default: + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); + break; + } mLOG(DS_MEM, STUB, "Unimplemented DS9 Store32: %08X:%08X", address, value); break; }@@ -845,14 +861,14 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < memory->itcmSize) { STORE_16(value, address & (DS9_SIZE_ITCM - 1), memory->itcm); break; } mLOG(DS_MEM, STUB, "Bad DS9 Store16: %08X:%04X", address, value); break; case DS_REGION_RAM: - if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { STORE_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); break; }@@ -866,6 +882,10 @@ case DS_REGION_IO:
DS9IOWrite(ds, address & 0x00FFFFFF, value); break; default: + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + STORE_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); + break; + } mLOG(DS_MEM, STUB, "Unimplemented DS9 Store16: %08X:%04X", address, value); break; }@@ -884,14 +904,14 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + if (address < memory->itcmSize) { ((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)] = value; break; } mLOG(DS_MEM, STUB, "Bad DS9 Store8: %08X:%02X", address, value); break; case DS_REGION_RAM: - if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)] = value; break; }@@ -904,6 +924,10 @@ case DS_REGION_IO:
DS9IOWrite8(ds, address & 0x00FFFFFF, value); break; default: + if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)] = value; + break; + } mLOG(DS_MEM, STUB, "Unimplemented DS9 Store8: %08X:%02X", address, value); break; }@@ -939,7 +963,7 @@ address &= 0xFFFFFFFC;
switch (address >> DS_BASE_OFFSET) { case DS_REGION_RAM: - LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); } else if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) { LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);@@ -948,8 +972,11 @@ mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address);
}); break; default: - mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address); - LDM_LOOP(value = 0); + LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); + } else { + mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address); + }); break; }@@ -996,14 +1023,14 @@
switch (address >> DS_BASE_OFFSET) { case DS9_REGION_ITCM: case DS9_REGION_ITCM_MIRROR: - STM_LOOP(if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) { + STM_LOOP(if (address < memory->itcmSize) { STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm); } else { mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value); }); break; case DS_REGION_RAM: - STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == DS9_BASE_DTCM) { + STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); } else if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) { STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);@@ -1012,8 +1039,11 @@ mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
}); break; default: - mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address); - STM_LOOP(); + STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) { + STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm); + } else { + mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address); + }); break; }