all repos — mgba @ bb83e78af97e3da21522a75c7349d6b52e86804a

mGBA Game Boy Advance Emulator

src/ds/memory.c (view raw)

   1/* Copyright (c) 2013-2016 Jeffrey Pfau
   2 *
   3 * This Source Code Form is subject to the terms of the Mozilla Public
   4 * License, v. 2.0. If a copy of the MPL was not distributed with this
   5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
   6#include <mgba/internal/ds/memory.h>
   7
   8#include <mgba/internal/arm/macros.h>
   9
  10#include <mgba/internal/ds/ds.h>
  11#include <mgba/internal/ds/io.h>
  12#include <mgba-util/math.h>
  13#include <mgba-util/memory.h>
  14
  15mLOG_DEFINE_CATEGORY(DS_MEM, "DS Memory");
  16
  17static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb
  18
  19static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t region);
  20static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t region);
  21static int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait);
  22
  23static const char DS7_BASE_WAITSTATES[16] =        { 0, 0, 8, 0, 0, 0, 0, 0 };
  24static const char DS7_BASE_WAITSTATES_32[16] =     { 0, 0, 9, 0, 0, 1, 1, 0 };
  25static const char DS7_BASE_WAITSTATES_SEQ[16] =    { 0, 0, 1, 0, 0, 0, 0, 0 };
  26static const char DS7_BASE_WAITSTATES_SEQ_32[16] = { 0, 0, 2, 0, 0, 1, 1, 0 };
  27
  28static const char DS9_BASE_WAITSTATES[16] =        { 6, 6, 17, 6, 6, 7, 7, 6 };
  29static const char DS9_BASE_WAITSTATES_32[16] =     { 6, 6, 19, 6, 6, 9, 9, 6 };
  30static const char DS9_BASE_WAITSTATES_SEQ[16] =    { 1, 1,  1, 1, 1, 2, 2, 1 };
  31static const char DS9_BASE_WAITSTATES_SEQ_32[16] = { 1, 1,  3, 1, 1, 4, 4, 1 };
  32
  33void DSMemoryInit(struct DS* ds) {
  34	struct ARMCore* arm7 = ds->ds7.cpu;
  35	arm7->memory.load32 = DS7Load32;
  36	arm7->memory.load16 = DS7Load16;
  37	arm7->memory.load8 = DS7Load8;
  38	arm7->memory.loadMultiple = DS7LoadMultiple;
  39	arm7->memory.store32 = DS7Store32;
  40	arm7->memory.store16 = DS7Store16;
  41	arm7->memory.store8 = DS7Store8;
  42	arm7->memory.storeMultiple = DS7StoreMultiple;
  43	arm7->memory.stall = DSMemoryStall;
  44
  45	struct ARMCore* arm9 = ds->ds9.cpu;
  46	arm9->memory.load32 = DS9Load32;
  47	arm9->memory.load16 = DS9Load16;
  48	arm9->memory.load8 = DS9Load8;
  49	arm9->memory.loadMultiple = DS9LoadMultiple;
  50	arm9->memory.store32 = DS9Store32;
  51	arm9->memory.store16 = DS9Store16;
  52	arm9->memory.store8 = DS9Store8;
  53	arm9->memory.storeMultiple = DS9StoreMultiple;
  54	arm9->memory.stall = DSMemoryStall;
  55
  56	int i;
  57	for (i = 0; i < 8; ++i) {
  58		// TODO: Formalize
  59		ds->ds7.memory.waitstatesNonseq16[i] = DS7_BASE_WAITSTATES[i];
  60		ds->ds7.memory.waitstatesSeq16[i] = DS7_BASE_WAITSTATES_SEQ[i];
  61		ds->ds7.memory.waitstatesPrefetchNonseq16[i] = DS7_BASE_WAITSTATES[i];
  62		ds->ds7.memory.waitstatesPrefetchSeq16[i] = DS7_BASE_WAITSTATES_SEQ[i];
  63		ds->ds7.memory.waitstatesNonseq32[i] = DS7_BASE_WAITSTATES_32[i];
  64		ds->ds7.memory.waitstatesSeq32[i] = DS7_BASE_WAITSTATES_SEQ_32[i];
  65		ds->ds7.memory.waitstatesPrefetchNonseq32[i] = DS7_BASE_WAITSTATES_32[i];
  66		ds->ds7.memory.waitstatesPrefetchSeq32[i] = DS7_BASE_WAITSTATES_SEQ_32[i];
  67
  68		ds->ds9.memory.waitstatesNonseq16[i] = DS9_BASE_WAITSTATES[i];
  69		ds->ds9.memory.waitstatesSeq16[i] = DS9_BASE_WAITSTATES_SEQ[i];
  70		ds->ds9.memory.waitstatesPrefetchNonseq16[i] = DS9_BASE_WAITSTATES[i];
  71		ds->ds9.memory.waitstatesPrefetchSeq16[i] = DS9_BASE_WAITSTATES[i];
  72		ds->ds9.memory.waitstatesNonseq32[i] = DS9_BASE_WAITSTATES_32[i];
  73		ds->ds9.memory.waitstatesSeq32[i] = DS9_BASE_WAITSTATES_SEQ_32[i];
  74		ds->ds9.memory.waitstatesPrefetchNonseq32[i] = DS9_BASE_WAITSTATES_32[i];
  75		ds->ds9.memory.waitstatesPrefetchSeq32[i] = DS9_BASE_WAITSTATES_32[i];
  76	}
  77	for (; i < 256; ++i) {
  78		ds->ds7.memory.waitstatesNonseq16[i] = 0;
  79		ds->ds7.memory.waitstatesSeq16[i] = 0;
  80		ds->ds7.memory.waitstatesNonseq32[i] = 0;
  81		ds->ds7.memory.waitstatesSeq32[i] = 0;
  82
  83		ds->ds9.memory.waitstatesNonseq16[i] = 0;
  84		ds->ds9.memory.waitstatesSeq16[i] = 0;
  85		ds->ds9.memory.waitstatesNonseq32[i] = 0;
  86		ds->ds9.memory.waitstatesSeq32[i] = 0;
  87	}
  88
  89	ds->memory.bios7 = NULL;
  90	ds->memory.bios9 = NULL;
  91	ds->memory.wram = NULL;
  92	ds->memory.wram7 = NULL;
  93	ds->memory.ram = NULL;
  94	ds->memory.itcm = NULL;
  95	ds->memory.dtcm = NULL;
  96	ds->memory.rom = NULL;
  97
  98	ds->ds7.memory.activeRegion = -1;
  99	ds->ds9.memory.activeRegion = -1;
 100	ds->ds7.memory.io = ds->memory.io7;
 101	ds->ds9.memory.io = ds->memory.io9;
 102
 103	arm7->memory.activeRegion = 0;
 104	arm7->memory.activeMask = 0;
 105	arm7->memory.setActiveRegion = DS7SetActiveRegion;
 106	arm7->memory.activeSeqCycles32 = 0;
 107	arm7->memory.activeSeqCycles16 = 0;
 108	arm7->memory.activeNonseqCycles32 = 0;
 109	arm7->memory.activeNonseqCycles16 = 0;
 110
 111	arm9->memory.activeRegion = 0;
 112	arm9->memory.activeMask = 0;
 113	arm9->memory.setActiveRegion = DS9SetActiveRegion;
 114	arm9->memory.activeSeqCycles32 = 0;
 115	arm9->memory.activeSeqCycles16 = 0;
 116	arm9->memory.activeNonseqCycles32 = 0;
 117	arm9->memory.activeNonseqCycles16 = 0;
 118}
 119
 120void DSMemoryDeinit(struct DS* ds) {
 121	mappedMemoryFree(ds->memory.wram, DS_SIZE_WORKING_RAM);
 122	mappedMemoryFree(ds->memory.wram7, DS7_SIZE_WORKING_RAM);
 123	mappedMemoryFree(ds->memory.ram, DS_SIZE_RAM);
 124	mappedMemoryFree(ds->memory.itcm, DS9_SIZE_ITCM);
 125	mappedMemoryFree(ds->memory.dtcm, DS9_SIZE_DTCM);
 126}
 127
 128void DSMemoryReset(struct DS* ds) {
 129	if (ds->memory.wram) {
 130		mappedMemoryFree(ds->memory.wram, DS_SIZE_WORKING_RAM);
 131	}
 132	ds->memory.wram = anonymousMemoryMap(DS_SIZE_WORKING_RAM);
 133
 134	if (ds->memory.wram7) {
 135		mappedMemoryFree(ds->memory.wram7, DS7_SIZE_WORKING_RAM);
 136	}
 137	ds->memory.wram7 = anonymousMemoryMap(DS7_SIZE_WORKING_RAM);
 138
 139	if (ds->memory.ram) {
 140		mappedMemoryFree(ds->memory.ram, DS_SIZE_RAM);
 141	}
 142	ds->memory.ram = anonymousMemoryMap(DS_SIZE_RAM);
 143
 144	if (ds->memory.itcm) {
 145		mappedMemoryFree(ds->memory.itcm, DS9_SIZE_ITCM);
 146	}
 147	ds->memory.itcm = anonymousMemoryMap(DS9_SIZE_ITCM);
 148
 149	if (ds->memory.dtcm) {
 150		mappedMemoryFree(ds->memory.dtcm, DS9_SIZE_DTCM);
 151	}
 152	ds->memory.dtcm = anonymousMemoryMap(DS9_SIZE_DTCM);
 153
 154	memset(ds->ds7.memory.dma, 0, sizeof(ds->ds7.memory.dma));
 155	memset(ds->ds9.memory.dma, 0, sizeof(ds->ds9.memory.dma));
 156	ds->ds7.memory.activeDMA = -1;
 157	ds->ds9.memory.activeDMA = -1;
 158
 159	// TODO: Correct size
 160	ds->memory.wramSize7 = 0x8000;
 161	ds->memory.wramSize9 = 0;
 162
 163	if (!ds->memory.wram || !ds->memory.wram7 || !ds->memory.ram || !ds->memory.itcm || !ds->memory.dtcm) {
 164		DSMemoryDeinit(ds);
 165		mLOG(DS_MEM, FATAL, "Could not map memory");
 166	}
 167}
 168
 169static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t address) {
 170	struct DS* ds = (struct DS*) cpu->master;
 171	struct DSCoreMemory* memory = &ds->ds7.memory;
 172
 173	int newRegion = address >> DS_BASE_OFFSET;
 174
 175	memory->activeRegion = newRegion;
 176	switch (newRegion) {
 177	case DS_REGION_WORKING_RAM:
 178		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 179			cpu->memory.activeRegion = ds->memory.wram7;
 180			cpu->memory.activeMask = DS7_SIZE_WORKING_RAM - 1;
 181		} else {
 182			cpu->memory.activeRegion = ds->memory.wram;
 183			cpu->memory.activeMask = ds->memory.wramSize7 - 1;
 184		}
 185		break;
 186	case DS7_REGION_BIOS:
 187		if (ds->memory.bios7) {
 188			cpu->memory.activeRegion = ds->memory.bios7;
 189			cpu->memory.activeMask = DS9_SIZE_BIOS - 1;
 190		} else {
 191			cpu->memory.activeRegion = _deadbeef;
 192			cpu->memory.activeMask = 0;
 193		}
 194		break;
 195	case DS_REGION_RAM:
 196		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 197			cpu->memory.activeRegion = ds->memory.ram;
 198			cpu->memory.activeMask = DS_SIZE_RAM - 1;
 199			break;
 200		}
 201	// Fall through
 202	default:
 203		memory->activeRegion = -1;
 204		cpu->memory.activeRegion = _deadbeef;
 205		cpu->memory.activeMask = 0;
 206		mLOG(DS_MEM, FATAL, "Jumped to invalid address: %08X", address);
 207		break;
 208	}
 209	cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
 210	cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
 211	cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
 212	cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
 213}
 214
 215uint32_t DS7Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 216	struct DS* ds = (struct DS*) cpu->master;
 217	struct DSMemory* memory = &ds->memory;
 218	uint32_t value = 0;
 219	int wait = ds->ds7.memory.waitstatesNonseq32[address >> DS_BASE_OFFSET];
 220
 221	switch (address >> DS_BASE_OFFSET) {
 222	case DS7_REGION_BIOS:
 223		LOAD_32(value, address & (DS7_SIZE_BIOS - 1), memory->bios7);
 224		break;
 225	case DS_REGION_WORKING_RAM:
 226		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 227			LOAD_32(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7);
 228		} else {
 229			LOAD_32(value, address & (ds->memory.wramSize7 - 1), memory->wram);
 230		}
 231		break;
 232	case DS_REGION_RAM:
 233		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 234			LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 235			break;
 236		}
 237		mLOG(DS_MEM, STUB, "Unimplemented DS7 Load32: %08X", address);
 238		break;
 239	case DS_REGION_IO:
 240		value = DS7IORead32(ds, address & 0x00FFFFFC);
 241		break;
 242	default:
 243		mLOG(DS_MEM, STUB, "Unimplemented DS7 Load32: %08X", address);
 244		break;
 245	}
 246
 247	if (cycleCounter) {
 248		wait += 2;
 249		*cycleCounter += wait;
 250	}
 251	// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
 252	int rotate = (address & 3) << 3;
 253	return ROR(value, rotate);
 254}
 255
 256uint32_t DS7Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 257	struct DS* ds = (struct DS*) cpu->master;
 258	struct DSMemory* memory = &ds->memory;
 259	uint32_t value = 0;
 260	int wait = ds->ds7.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 261
 262	switch (address >> DS_BASE_OFFSET) {
 263	case DS7_REGION_BIOS:
 264		LOAD_16(value, address & (DS7_SIZE_BIOS - 1), memory->bios7);
 265		break;
 266	case DS_REGION_WORKING_RAM:
 267		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 268			LOAD_16(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7);
 269		} else {
 270			LOAD_16(value, address & (ds->memory.wramSize7 - 1), memory->wram);
 271		}
 272		break;
 273	case DS_REGION_RAM:
 274		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 275			LOAD_16(value, address & (DS_SIZE_RAM - 1), memory->ram);
 276			break;
 277		}
 278		mLOG(DS_MEM, STUB, "Unimplemented DS7 Load16: %08X", address);
 279	case DS_REGION_IO:
 280		value = DS7IORead(ds, address & 0x00FFFFFF);
 281		break;
 282	default:
 283		mLOG(DS_MEM, STUB, "Unimplemented DS7 Load16: %08X", address);
 284		break;
 285	}
 286
 287	if (cycleCounter) {
 288		wait += 2;
 289		*cycleCounter += wait;
 290	}
 291	// Unaligned 16-bit loads are "unpredictable", TODO: See what DS does
 292	int rotate = (address & 1) << 3;
 293	return ROR(value, rotate);
 294}
 295
 296uint32_t DS7Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 297	struct DS* ds = (struct DS*) cpu->master;
 298	struct DSMemory* memory = &ds->memory;
 299	uint32_t value = 0;
 300	int wait = ds->ds7.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 301
 302	switch (address >> DS_BASE_OFFSET) {
 303	case DS_REGION_WORKING_RAM:
 304		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 305			value = ((uint8_t*) memory->wram7)[address & (DS7_SIZE_WORKING_RAM - 1)];
 306		} else {
 307			value = ((uint8_t*) memory->wram)[address & (ds->memory.wramSize7 - 1)];
 308		}
 309		break;
 310	case DS_REGION_RAM:
 311		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 312			value = ((uint8_t*) memory->ram)[address & (DS_SIZE_RAM - 1)];
 313			break;
 314		}
 315		mLOG(DS_MEM, STUB, "Unimplemented DS7 Load8: %08X", address);
 316	default:
 317		mLOG(DS_MEM, STUB, "Unimplemented DS7 Load8: %08X", address);
 318		break;
 319	}
 320
 321	if (cycleCounter) {
 322		wait += 2;
 323		*cycleCounter += wait;
 324	}
 325	return value;
 326}
 327
 328void DS7Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
 329	struct DS* ds = (struct DS*) cpu->master;
 330	struct DSMemory* memory = &ds->memory;
 331	int wait = ds->ds7.memory.waitstatesNonseq32[address >> DS_BASE_OFFSET];
 332
 333	switch (address >> DS_BASE_OFFSET) {
 334	case DS_REGION_WORKING_RAM:
 335		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 336			STORE_32(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7);
 337		} else {
 338			STORE_32(value, address & (ds->memory.wramSize7 - 1), memory->wram);
 339		}
 340		break;
 341	case DS_REGION_RAM:
 342		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 343			STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 344			break;
 345		}
 346		mLOG(DS_MEM, STUB, "Unimplemented DS7 Store32: %08X:%08X", address, value);
 347		break;
 348	case DS_REGION_IO:
 349		DS7IOWrite32(ds, address & 0x00FFFFFF, value);
 350		break;
 351	default:
 352		mLOG(DS_MEM, STUB, "Unimplemented DS7 Store32: %08X:%08X", address, value);
 353		break;
 354	}
 355
 356	if (cycleCounter) {
 357		++wait;
 358		*cycleCounter += wait;
 359	}
 360}
 361
 362void DS7Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
 363	struct DS* ds = (struct DS*) cpu->master;
 364	struct DSMemory* memory = &ds->memory;
 365	int wait = ds->ds7.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 366
 367	switch (address >> DS_BASE_OFFSET) {
 368	case DS_REGION_WORKING_RAM:
 369		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 370			STORE_16(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7);
 371		} else {
 372			STORE_16(value, address & (ds->memory.wramSize7 - 1), memory->wram);
 373		}
 374		break;
 375	case DS_REGION_RAM:
 376		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 377			STORE_16(value, address & (DS_SIZE_RAM - 1), memory->ram);
 378			break;
 379		}
 380		mLOG(DS_MEM, STUB, "Unimplemented DS7 Store16: %08X:%04X", address, value);
 381		break;
 382	case DS_REGION_IO:
 383		DS7IOWrite(ds, address & 0x00FFFFFF, value);
 384		break;
 385	default:
 386		mLOG(DS_MEM, STUB, "Unimplemented DS7 Store16: %08X:%04X", address, value);
 387		break;
 388	}
 389
 390	if (cycleCounter) {
 391		++wait;
 392		*cycleCounter += wait;
 393	}
 394}
 395
 396void DS7Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
 397	struct DS* ds = (struct DS*) cpu->master;
 398	struct DSMemory* memory = &ds->memory;
 399	int wait = ds->ds7.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 400
 401	switch (address >> DS_BASE_OFFSET) {
 402	case DS_REGION_WORKING_RAM:
 403		if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 404			((uint8_t*) memory->wram7)[address & (DS7_SIZE_WORKING_RAM - 1)] = value;
 405		} else {
 406			((uint8_t*) memory->wram)[address & (ds->memory.wramSize7 - 1)] = value;
 407		}
 408		break;
 409	case DS_REGION_RAM:
 410		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 411			((uint8_t*) memory->ram)[address & (DS_SIZE_RAM - 1)] = value;
 412			break;
 413		}
 414		mLOG(DS_MEM, STUB, "Unimplemented DS7 Store8: %08X:%02X", address, value);
 415	case DS_REGION_IO:
 416		DS7IOWrite8(ds, address & 0x00FFFFFF, value);
 417		break;
 418	default:
 419		mLOG(DS_MEM, STUB, "Unimplemented DS7 Store8: %08X:%02X", address, value);
 420		break;
 421	}
 422
 423	if (cycleCounter) {
 424		++wait;
 425		*cycleCounter += wait;
 426	}
 427}
 428
 429#define LDM_LOOP(LDM) \
 430	for (i = 0; i < 16; i += 4) { \
 431		if (UNLIKELY(mask & (1 << i))) { \
 432			LDM; \
 433			cpu->gprs[i] = value; \
 434			++wait; \
 435			wait += ws32[address >> DS_BASE_OFFSET]; \
 436			address += 4; \
 437		} \
 438		if (UNLIKELY(mask & (2 << i))) { \
 439			LDM; \
 440			cpu->gprs[i + 1] = value; \
 441			++wait; \
 442			wait += ws32[address >> DS_BASE_OFFSET]; \
 443			address += 4; \
 444		} \
 445		if (UNLIKELY(mask & (4 << i))) { \
 446			LDM; \
 447			cpu->gprs[i + 2] = value; \
 448			++wait; \
 449			wait += ws32[address >> DS_BASE_OFFSET]; \
 450			address += 4; \
 451		} \
 452		if (UNLIKELY(mask & (8 << i))) { \
 453			LDM; \
 454			cpu->gprs[i + 3] = value; \
 455			++wait; \
 456			wait += ws32[address >> DS_BASE_OFFSET]; \
 457			address += 4; \
 458		} \
 459	}
 460
 461#define STM_LOOP(STM) \
 462	for (i = 0; i < 16; i += 4) { \
 463		if (UNLIKELY(mask & (1 << i))) { \
 464			value = cpu->gprs[i]; \
 465			STM; \
 466			++wait; \
 467			wait += ws32[address >> DS_BASE_OFFSET]; \
 468			address += 4; \
 469		} \
 470		if (UNLIKELY(mask & (2 << i))) { \
 471			value = cpu->gprs[i + 1]; \
 472			STM; \
 473			++wait; \
 474			wait += ws32[address >> DS_BASE_OFFSET]; \
 475			address += 4; \
 476		} \
 477		if (UNLIKELY(mask & (4 << i))) { \
 478			value = cpu->gprs[i + 2]; \
 479			STM; \
 480			++wait; \
 481			wait += ws32[address >> DS_BASE_OFFSET]; \
 482			address += 4; \
 483		} \
 484		if (UNLIKELY(mask & (8 << i))) { \
 485			value = cpu->gprs[i + 3]; \
 486			STM; \
 487			++wait; \
 488			wait += ws32[address >> DS_BASE_OFFSET]; \
 489			address += 4; \
 490		} \
 491	}
 492
 493
 494
 495uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
 496	struct DS* ds = (struct DS*) cpu->master;
 497	struct DSMemory* memory = &ds->memory;
 498	char* ws32 = ds->ds7.memory.waitstatesNonseq32;
 499	uint32_t value;
 500	int wait = 0;
 501
 502	int i;
 503	int offset = 4;
 504	int popcount = 0;
 505	if (direction & LSM_D) {
 506		offset = -4;
 507		popcount = popcount32(mask);
 508		address -= (popcount << 2) - 4;
 509	}
 510
 511	if (direction & LSM_B) {
 512		address += offset;
 513	}
 514
 515	uint32_t addressMisalign = address & 0x3;
 516	address &= 0xFFFFFFFC;
 517
 518	switch (address >> DS_BASE_OFFSET) {
 519	case DS_REGION_WORKING_RAM:
 520		LDM_LOOP(if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 521			LOAD_32(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7);
 522		} else {
 523			LOAD_32(value, address & (ds->memory.wramSize7 - 1), memory->wram);
 524		});
 525		break;
 526	case DS_REGION_RAM:
 527		LDM_LOOP(if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 528			LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 529		} else {
 530			mLOG(DS_MEM, STUB, "Unimplemented DS7 LDM: %08X", address);
 531		});
 532		break;
 533	case DS_REGION_IO:
 534		LDM_LOOP(value = DS7IORead32(ds, address));
 535		break;
 536	default:
 537		mLOG(DS_MEM, STUB, "Unimplemented DS7 LDM: %08X", address);
 538		LDM_LOOP(value = 0);
 539	}
 540
 541	if (cycleCounter) {
 542		++wait;
 543		*cycleCounter += wait;
 544	}
 545
 546	if (direction & LSM_B) {
 547		address -= offset;
 548	}
 549
 550	if (direction & LSM_D) {
 551		address -= (popcount << 2) + 4;
 552	}
 553
 554	return address | addressMisalign;
 555}
 556
 557
 558uint32_t DS7StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
 559	struct DS* ds = (struct DS*) cpu->master;
 560	struct DSMemory* memory = &ds->memory;
 561	char* ws32 = ds->ds7.memory.waitstatesNonseq32;
 562	uint32_t value;
 563	int wait = 0;
 564
 565	int i;
 566	int offset = 4;
 567	int popcount = 0;
 568	if (direction & LSM_D) {
 569		offset = -4;
 570		popcount = popcount32(mask);
 571		address -= (popcount << 2) - 4;
 572	}
 573
 574	if (direction & LSM_B) {
 575		address += offset;
 576	}
 577
 578	uint32_t addressMisalign = address & 0x3;
 579	address &= 0xFFFFFFFC;
 580
 581	switch (address >> DS_BASE_OFFSET) {
 582	case DS_REGION_WORKING_RAM:
 583		STM_LOOP(if (address >= DS7_BASE_WORKING_RAM || !ds->memory.wramSize7) {
 584			STORE_32(value, address & (DS7_SIZE_WORKING_RAM - 1), memory->wram7);
 585		} else {
 586			STORE_32(value, address & (ds->memory.wramSize7 - 1), memory->wram);
 587		});
 588		break;
 589	case DS_REGION_RAM:
 590		STM_LOOP(if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 591			STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 592		} else {
 593			mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
 594		});
 595		break;
 596	default:
 597		mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
 598		STM_LOOP();
 599		break;
 600	}
 601
 602	if (cycleCounter) {
 603		*cycleCounter += wait;
 604	}
 605
 606	if (direction & LSM_B) {
 607		address -= offset;
 608	}
 609
 610	if (direction & LSM_D) {
 611		address -= (popcount << 2) + 4;
 612	}
 613
 614	return address | addressMisalign;
 615}
 616
 617static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t address) {
 618	struct DS* ds = (struct DS*) cpu->master;
 619	struct DSCoreMemory* memory = &ds->ds9.memory;
 620
 621	int newRegion = address >> DS_BASE_OFFSET;
 622
 623	memory->activeRegion = newRegion;
 624	switch (newRegion) {
 625	case DS9_REGION_ITCM:
 626	case DS9_REGION_ITCM_MIRROR:
 627		if (address < ds->memory.itcmSize) {
 628			cpu->memory.activeRegion = ds->memory.itcm;
 629			cpu->memory.activeMask = DS9_SIZE_ITCM - 1;
 630			break;
 631		}
 632		goto jump_error;
 633	case DS_REGION_RAM:
 634		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 635			cpu->memory.activeRegion = ds->memory.ram;
 636			cpu->memory.activeMask = DS_SIZE_RAM - 1;
 637			break;
 638		}
 639		goto jump_error;
 640	case DS9_REGION_BIOS:
 641		// TODO: Mask properly
 642		if (ds->memory.bios9) {
 643			cpu->memory.activeRegion = ds->memory.bios9;
 644			cpu->memory.activeMask = DS9_SIZE_BIOS - 1;
 645		} else {
 646			cpu->memory.activeRegion = _deadbeef;
 647			cpu->memory.activeMask = 0;
 648		}
 649		break;
 650	default:
 651	jump_error:
 652		memory->activeRegion = -1;
 653		cpu->memory.activeRegion = _deadbeef;
 654		cpu->memory.activeMask = 0;
 655		mLOG(DS_MEM, FATAL, "Jumped to invalid address: %08X", address);
 656		return;
 657	}
 658	cpu->memory.activeSeqCycles32 = memory->waitstatesPrefetchSeq32[memory->activeRegion];
 659	cpu->memory.activeSeqCycles16 = memory->waitstatesPrefetchSeq16[memory->activeRegion];
 660	cpu->memory.activeNonseqCycles32 = memory->waitstatesPrefetchNonseq32[memory->activeRegion];
 661	cpu->memory.activeNonseqCycles16 = memory->waitstatesPrefetchNonseq16[memory->activeRegion];
 662}
 663
 664uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 665	struct DS* ds = (struct DS*) cpu->master;
 666	struct DSMemory* memory = &ds->memory;
 667	uint32_t value = 0;
 668	int wait = ds->ds9.memory.waitstatesNonseq32[address >> DS_BASE_OFFSET];
 669
 670	switch (address >> DS_BASE_OFFSET) {
 671	case DS9_REGION_ITCM:
 672	case DS9_REGION_ITCM_MIRROR:
 673		if (address < memory->itcmSize) {
 674			LOAD_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
 675			break;
 676		}
 677		mLOG(DS_MEM, STUB, "Bad DS9 Load32: %08X:%08X", address, value);
 678		break;
 679	case DS_REGION_RAM:
 680		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 681			LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 682			break;
 683		}
 684		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 685			LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 686			break;
 687		}
 688		mLOG(DS_MEM, STUB, "Unimplemented DS9 Load32: %08X", address);
 689		break;
 690	case DS_REGION_IO:
 691		value = DS9IORead32(ds, address & 0x00FFFFFC);
 692		break;
 693	case DS9_REGION_BIOS:
 694		// TODO: Fix undersized BIOS
 695		// TODO: Fix masking
 696		LOAD_32(value, address & (DS9_SIZE_BIOS - 1), memory->bios9);
 697		break;
 698	default:
 699		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 700			LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 701			break;
 702		}
 703		mLOG(DS_MEM, STUB, "Unimplemented DS9 Load32: %08X", address);
 704		break;
 705	}
 706
 707	if (cycleCounter) {
 708		wait += 2;
 709		*cycleCounter += wait;
 710	}
 711	// Unaligned 32-bit loads are "rotated" so they make some semblance of sense
 712	int rotate = (address & 3) << 3;
 713	return ROR(value, rotate);
 714}
 715
 716uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 717	struct DS* ds = (struct DS*) cpu->master;
 718	struct DSMemory* memory = &ds->memory;
 719	uint32_t value = 0;
 720	int wait = ds->ds9.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 721
 722	switch (address >> DS_BASE_OFFSET) {
 723	case DS9_REGION_ITCM:
 724	case DS9_REGION_ITCM_MIRROR:
 725		if (address < memory->itcmSize) {
 726			LOAD_16(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
 727			break;
 728		}
 729		mLOG(DS_MEM, STUB, "Bad DS9 Load16: %08X:%08X", address, value);
 730		break;
 731	case DS_REGION_RAM:
 732		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 733			LOAD_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 734			break;
 735		}
 736		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 737			LOAD_16(value, address & (DS_SIZE_RAM - 1), memory->ram);
 738			break;
 739		}
 740		mLOG(DS_MEM, STUB, "Unimplemented DS9 Load16: %08X", address);
 741	case DS_REGION_IO:
 742		value = DS9IORead(ds, address & 0x00FFFFFF);
 743		break;
 744	case DS9_REGION_BIOS:
 745		// TODO: Fix undersized BIOS
 746		// TODO: Fix masking
 747		LOAD_16(value, address & (DS9_SIZE_BIOS - 1), memory->bios9);
 748		break;
 749	default:
 750		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 751			LOAD_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 752			break;
 753		}
 754		mLOG(DS_MEM, STUB, "Unimplemented DS9 Load16: %08X", address);
 755		break;
 756	}
 757
 758	if (cycleCounter) {
 759		wait += 2;
 760		*cycleCounter += wait;
 761	}
 762	// Unaligned 16-bit loads are "unpredictable", TODO: See what DS does
 763	int rotate = (address & 1) << 3;
 764	return ROR(value, rotate);
 765}
 766
 767uint32_t DS9Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
 768	struct DS* ds = (struct DS*) cpu->master;
 769	struct DSMemory* memory = &ds->memory;
 770	uint32_t value = 0;
 771	int wait = ds->ds9.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 772
 773	switch (address >> DS_BASE_OFFSET) {
 774	case DS9_REGION_ITCM:
 775	case DS9_REGION_ITCM_MIRROR:
 776		if (address < memory->itcmSize) {
 777			value = ((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)];
 778			break;
 779		}
 780		mLOG(DS_MEM, STUB, "Bad DS9 Load8: %08X:%08X", address, value);
 781		break;
 782	case DS_REGION_RAM:
 783		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 784			value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM- 1)];
 785			break;
 786		}
 787		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 788			value = ((uint8_t*) memory->ram)[address & (DS_SIZE_RAM - 1)];
 789			break;
 790		}
 791		mLOG(DS_MEM, STUB, "Unimplemented DS9 Load8: %08X", address);
 792	case DS9_REGION_BIOS:
 793		// TODO: Fix undersized BIOS
 794		// TODO: Fix masking
 795		value = ((uint8_t*) memory->bios9)[address & (DS9_SIZE_BIOS - 1)];
 796		break;
 797	default:
 798		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 799			value = ((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)];
 800			break;
 801		}
 802		mLOG(DS_MEM, STUB, "Unimplemented DS9 Load8: %08X", address);
 803		break;
 804	}
 805
 806	if (cycleCounter) {
 807		wait += 2;
 808		*cycleCounter += wait;
 809	}
 810	return value;
 811}
 812
 813void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
 814	struct DS* ds = (struct DS*) cpu->master;
 815	struct DSMemory* memory = &ds->memory;
 816	int wait = ds->ds9.memory.waitstatesNonseq32[address >> DS_BASE_OFFSET];
 817
 818	switch (address >> DS_BASE_OFFSET) {
 819	case DS9_REGION_ITCM:
 820	case DS9_REGION_ITCM_MIRROR:
 821		if (address < memory->itcmSize) {
 822			STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
 823			break;
 824		}
 825		mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value);
 826		break;
 827	case DS_REGION_RAM:
 828		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 829			STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 830			break;
 831		}
 832		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 833			STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 834			break;
 835		}
 836		mLOG(DS_MEM, STUB, "Unimplemented DS9 Store32: %08X:%08X", address, value);
 837		break;
 838	case DS_REGION_IO:
 839		DS9IOWrite32(ds, address & 0x00FFFFFF, value);
 840		break;
 841	default:
 842		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 843			STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 844			break;
 845		}
 846		mLOG(DS_MEM, STUB, "Unimplemented DS9 Store32: %08X:%08X", address, value);
 847		break;
 848	}
 849
 850	if (cycleCounter) {
 851		++wait;
 852		*cycleCounter += wait;
 853	}
 854}
 855
 856void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
 857	struct DS* ds = (struct DS*) cpu->master;
 858	struct DSMemory* memory = &ds->memory;
 859	int wait = ds->ds9.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 860
 861	switch (address >> DS_BASE_OFFSET) {
 862	case DS9_REGION_ITCM:
 863	case DS9_REGION_ITCM_MIRROR:
 864		if (address < memory->itcmSize) {
 865			STORE_16(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
 866			break;
 867		}
 868		mLOG(DS_MEM, STUB, "Bad DS9 Store16: %08X:%04X", address, value);
 869		break;
 870	case DS_REGION_RAM:
 871		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 872			STORE_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 873			break;
 874		}
 875		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 876			STORE_16(value, address & (DS_SIZE_RAM - 1), memory->ram);
 877			break;
 878		}
 879		mLOG(DS_MEM, STUB, "Unimplemented DS9 Store16: %08X:%04X", address, value);
 880		break;
 881	case DS_REGION_IO:
 882		DS9IOWrite(ds, address & 0x00FFFFFF, value);
 883		break;
 884	default:
 885		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 886			STORE_16(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 887			break;
 888		}
 889		mLOG(DS_MEM, STUB, "Unimplemented DS9 Store16: %08X:%04X", address, value);
 890		break;
 891	}
 892
 893	if (cycleCounter) {
 894		++wait;
 895		*cycleCounter += wait;
 896	}
 897}
 898
 899void DS9Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
 900	struct DS* ds = (struct DS*) cpu->master;
 901	struct DSMemory* memory = &ds->memory;
 902	int wait = ds->ds9.memory.waitstatesNonseq16[address >> DS_BASE_OFFSET];
 903
 904	switch (address >> DS_BASE_OFFSET) {
 905	case DS9_REGION_ITCM:
 906	case DS9_REGION_ITCM_MIRROR:
 907		if (address < memory->itcmSize) {
 908			((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)] = value;
 909			break;
 910		}
 911		mLOG(DS_MEM, STUB, "Bad DS9 Store8: %08X:%02X", address, value);
 912		break;
 913	case DS_REGION_RAM:
 914		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 915			((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)] = value;
 916			break;
 917		}
 918		if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 919			((uint8_t*) memory->ram)[address & (DS_SIZE_RAM - 1)] = value;
 920			break;
 921		}
 922		mLOG(DS_MEM, STUB, "Unimplemented DS9 Store8: %08X:%02X", address, value);
 923	case DS_REGION_IO:
 924		DS9IOWrite8(ds, address & 0x00FFFFFF, value);
 925		break;
 926	default:
 927		if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 928			((uint8_t*) memory->dtcm)[address & (DS9_SIZE_DTCM - 1)] = value;
 929			break;
 930		}
 931		mLOG(DS_MEM, STUB, "Unimplemented DS9 Store8: %08X:%02X", address, value);
 932		break;
 933	}
 934
 935	if (cycleCounter) {
 936		++wait;
 937		*cycleCounter += wait;
 938	}
 939}
 940
 941uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
 942	struct DS* ds = (struct DS*) cpu->master;
 943	struct DSMemory* memory = &ds->memory;
 944	char* ws32 = ds->ds9.memory.waitstatesNonseq32;
 945	uint32_t value;
 946	int wait = 0;
 947
 948	int i;
 949	int offset = 4;
 950	int popcount = 0;
 951	if (direction & LSM_D) {
 952		offset = -4;
 953		popcount = popcount32(mask);
 954		address -= (popcount << 2) - 4;
 955	}
 956
 957	if (direction & LSM_B) {
 958		address += offset;
 959	}
 960
 961	uint32_t addressMisalign = address & 0x3;
 962	address &= 0xFFFFFFFC;
 963
 964	switch (address >> DS_BASE_OFFSET) {
 965	case DS_REGION_RAM:
 966		LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 967			LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 968		} else if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
 969			LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
 970		} else {
 971			mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address);
 972		});
 973		break;
 974	case DS_REGION_IO:
 975		LDM_LOOP(value = DS9IORead32(ds, address));
 976		break;
 977	default:
 978		LDM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
 979			LOAD_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
 980		} else {
 981			mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address);
 982		});
 983		break;
 984	}
 985
 986	if (cycleCounter) {
 987		++wait;
 988		*cycleCounter += wait;
 989	}
 990
 991	if (direction & LSM_B) {
 992		address -= offset;
 993	}
 994
 995	if (direction & LSM_D) {
 996		address -= (popcount << 2) + 4;
 997	}
 998
 999	return address | addressMisalign;
1000}
1001
1002
1003uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
1004	struct DS* ds = (struct DS*) cpu->master;
1005	struct DSMemory* memory = &ds->memory;
1006	char* ws32 = ds->ds9.memory.waitstatesNonseq32;
1007	uint32_t value;
1008	int wait = 0;
1009
1010	int i;
1011	int offset = 4;
1012	int popcount = 0;
1013	if (direction & LSM_D) {
1014		offset = -4;
1015		popcount = popcount32(mask);
1016		address -= (popcount << 2) - 4;
1017	}
1018
1019	if (direction & LSM_B) {
1020		address += offset;
1021	}
1022
1023	uint32_t addressMisalign = address & 0x3;
1024	address &= 0xFFFFFFFC;
1025
1026	switch (address >> DS_BASE_OFFSET) {
1027	case DS9_REGION_ITCM:
1028	case DS9_REGION_ITCM_MIRROR:
1029		STM_LOOP(if (address < memory->itcmSize) {
1030			STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
1031		} else {
1032			mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value);
1033		});
1034		break;
1035	case DS_REGION_RAM:
1036		STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
1037			STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
1038		} else if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
1039			STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
1040		} else {
1041			mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
1042		});
1043		break;
1044	default:
1045		STM_LOOP(if ((address & ~(DS9_SIZE_DTCM - 1)) == memory->dtcmBase) {
1046			STORE_32(value, address & (DS9_SIZE_DTCM - 1), memory->dtcm);
1047		} else {
1048			mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
1049		});
1050		break;
1051	}
1052
1053	if (cycleCounter) {
1054		*cycleCounter += wait;
1055	}
1056
1057	if (direction & LSM_B) {
1058		address -= offset;
1059	}
1060
1061	if (direction & LSM_D) {
1062		address -= (popcount << 2) + 4;
1063	}
1064
1065	return address | addressMisalign;
1066}
1067
1068int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait) {
1069	return wait;
1070}
1071