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 "memory.h"
7
8#include "arm/macros.h"
9
10#include "ds/ds.h"
11#include "util/math.h"
12#include "util/memory.h"
13
14mLOG_DEFINE_CATEGORY(DS_MEM, "DS Memory");
15
16#define LDM_LOOP(LDM) \
17 for (i = 0; i < 16; i += 4) { \
18 if (UNLIKELY(mask & (1 << i))) { \
19 LDM; \
20 cpu->gprs[i] = value; \
21 ++wait; \
22 address += 4; \
23 } \
24 if (UNLIKELY(mask & (2 << i))) { \
25 LDM; \
26 cpu->gprs[i + 1] = value; \
27 ++wait; \
28 address += 4; \
29 } \
30 if (UNLIKELY(mask & (4 << i))) { \
31 LDM; \
32 cpu->gprs[i + 2] = value; \
33 ++wait; \
34 address += 4; \
35 } \
36 if (UNLIKELY(mask & (8 << i))) { \
37 LDM; \
38 cpu->gprs[i + 3] = value; \
39 ++wait; \
40 address += 4; \
41 } \
42 }
43
44#define STM_LOOP(STM) \
45 for (i = 0; i < 16; i += 4) { \
46 if (UNLIKELY(mask & (1 << i))) { \
47 value = cpu->gprs[i]; \
48 STM; \
49 ++wait; \
50 address += 4; \
51 } \
52 if (UNLIKELY(mask & (2 << i))) { \
53 value = cpu->gprs[i + 1]; \
54 STM; \
55 ++wait; \
56 address += 4; \
57 } \
58 if (UNLIKELY(mask & (4 << i))) { \
59 value = cpu->gprs[i + 2]; \
60 STM; \
61 ++wait; \
62 address += 4; \
63 } \
64 if (UNLIKELY(mask & (8 << i))) { \
65 value = cpu->gprs[i + 3]; \
66 STM; \
67 ++wait; \
68 address += 4; \
69 } \
70 }
71
72
73static uint32_t _deadbeef[1] = { 0xE710B710 }; // Illegal instruction on both ARM and Thumb
74
75static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t region);
76static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t region);
77static int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait);
78
79static const int DMA_OFFSET[] = { 1, -1, 0, 1 };
80
81void DSMemoryInit(struct DS* ds) {
82 struct ARMCore* arm7 = ds->arm7;
83 arm7->memory.load32 = DS7Load32;
84 arm7->memory.load16 = DS7Load16;
85 arm7->memory.load8 = DS7Load8;
86 arm7->memory.loadMultiple = DS7LoadMultiple;
87 arm7->memory.store32 = DS7Store32;
88 arm7->memory.store16 = DS7Store16;
89 arm7->memory.store8 = DS7Store8;
90 arm7->memory.storeMultiple = DS7StoreMultiple;
91 arm7->memory.stall = DSMemoryStall;
92
93 struct ARMCore* arm9 = ds->arm9;
94 arm9->memory.load32 = DS9Load32;
95 arm9->memory.load16 = DS9Load16;
96 arm9->memory.load8 = DS9Load8;
97 arm9->memory.loadMultiple = DS9LoadMultiple;
98 arm9->memory.store32 = DS9Store32;
99 arm9->memory.store16 = DS9Store16;
100 arm9->memory.store8 = DS9Store8;
101 arm9->memory.storeMultiple = DS9StoreMultiple;
102 arm9->memory.stall = DSMemoryStall;
103
104 ds->memory.bios7 = NULL;
105 ds->memory.bios9 = NULL;
106 ds->memory.wram = NULL;
107 ds->memory.ram = NULL;
108 ds->memory.itcm = NULL;
109 ds->memory.dtcm = NULL;
110 ds->memory.rom = NULL;
111
112 ds->memory.activeRegion7 = -1;
113 ds->memory.activeRegion9 = -1;
114
115 arm7->memory.activeRegion = 0;
116 arm7->memory.activeMask = 0;
117 arm7->memory.setActiveRegion = DS7SetActiveRegion;
118 arm7->memory.activeSeqCycles32 = 0;
119 arm7->memory.activeSeqCycles16 = 0;
120 arm7->memory.activeNonseqCycles32 = 0;
121 arm7->memory.activeNonseqCycles16 = 0;
122
123 arm9->memory.activeRegion = 0;
124 arm9->memory.activeMask = 0;
125 arm9->memory.setActiveRegion = DS9SetActiveRegion;
126 arm9->memory.activeSeqCycles32 = 0;
127 arm9->memory.activeSeqCycles16 = 0;
128 arm9->memory.activeNonseqCycles32 = 0;
129 arm9->memory.activeNonseqCycles16 = 0;
130}
131
132void DSMemoryDeinit(struct DS* ds) {
133 mappedMemoryFree(ds->memory.wram, DS_SIZE_WORKING_RAM);
134 mappedMemoryFree(ds->memory.ram, DS_SIZE_RAM);
135 mappedMemoryFree(ds->memory.itcm, DS9_SIZE_ITCM);
136 mappedMemoryFree(ds->memory.dtcm, DS9_SIZE_DTCM);
137}
138
139void DSMemoryReset(struct DS* ds) {
140 if (ds->memory.wram) {
141 mappedMemoryFree(ds->memory.wram, DS_SIZE_WORKING_RAM);
142 }
143 ds->memory.wram = anonymousMemoryMap(DS_SIZE_WORKING_RAM);
144
145 if (ds->memory.ram) {
146 mappedMemoryFree(ds->memory.ram, DS_SIZE_RAM);
147 }
148 ds->memory.ram = anonymousMemoryMap(DS_SIZE_RAM);
149
150 if (ds->memory.itcm) {
151 mappedMemoryFree(ds->memory.itcm, DS9_SIZE_ITCM);
152 }
153 ds->memory.itcm = anonymousMemoryMap(DS9_SIZE_ITCM);
154
155 if (ds->memory.dtcm) {
156 mappedMemoryFree(ds->memory.dtcm, DS9_SIZE_DTCM);
157 }
158 ds->memory.dtcm = anonymousMemoryMap(DS9_SIZE_DTCM);
159
160 memset(ds->memory.dma7, 0, sizeof(ds->memory.dma7));
161 memset(ds->memory.dma9, 0, sizeof(ds->memory.dma9));
162 ds->memory.activeDMA7 = -1;
163 ds->memory.activeDMA9 = -1;
164 ds->memory.nextDMA = INT_MAX;
165 ds->memory.eventDiff = 0;
166
167 if (!ds->memory.wram || !ds->memory.ram || !ds->memory.itcm || !ds->memory.dtcm) {
168 DSMemoryDeinit(ds);
169 mLOG(DS_MEM, FATAL, "Could not map memory");
170 }
171}
172
173static void DS7SetActiveRegion(struct ARMCore* cpu, uint32_t address) {
174 struct DS* ds = (struct DS*) cpu->master;
175 struct DSMemory* memory = &ds->memory;
176
177 int newRegion = address >> DS_BASE_OFFSET;
178
179 memory->activeRegion7 = newRegion;
180 switch (newRegion) {
181 case DS_REGION_RAM:
182 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
183 cpu->memory.activeRegion = memory->ram;
184 cpu->memory.activeMask = DS_SIZE_RAM - 1;
185 return;
186 }
187 break;
188 case DS7_REGION_BIOS:
189 if (memory->bios7) {
190 cpu->memory.activeRegion = memory->bios9;
191 cpu->memory.activeMask = DS9_SIZE_BIOS - 1;
192 } else {
193 cpu->memory.activeRegion = _deadbeef;
194 cpu->memory.activeMask = 0;
195 }
196 return;
197 default:
198 break;
199 }
200 cpu->memory.activeRegion = _deadbeef;
201 cpu->memory.activeMask = 0;
202 mLOG(DS_MEM, FATAL, "Jumped to invalid address: %08X", address);
203 return;
204}
205
206uint32_t DS7Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
207 struct DS* ds = (struct DS*) cpu->master;
208 struct DSMemory* memory = &ds->memory;
209 uint32_t value = 0;
210 int wait = 0;
211
212 switch (address >> DS_BASE_OFFSET) {
213 case DS_REGION_RAM:
214 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
215 LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
216 }
217 break;
218 default:
219 break;
220 }
221
222 if (cycleCounter) {
223 wait += 2;
224 *cycleCounter += wait;
225 }
226 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
227 int rotate = (address & 3) << 3;
228 return ROR(value, rotate);
229}
230
231uint32_t DS7Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
232 struct DS* ds = (struct DS*) cpu->master;
233 struct DSMemory* memory = &ds->memory;
234 uint32_t value = 0;
235 int wait = 0;
236
237 switch (address >> DS_BASE_OFFSET) {
238 default:
239 break;
240 }
241
242 if (cycleCounter) {
243 wait += 2;
244 *cycleCounter += wait;
245 }
246 // Unaligned 16-bit loads are "unpredictable", TODO: See what DS does
247 int rotate = (address & 1) << 3;
248 return ROR(value, rotate);
249}
250
251uint32_t DS7Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
252 struct DS* ds = (struct DS*) cpu->master;
253 struct DSMemory* memory = &ds->memory;
254 uint32_t value = 0;
255 int wait = 0;
256
257 switch (address >> DS_BASE_OFFSET) {
258 default:
259 break;
260 }
261
262 if (cycleCounter) {
263 wait += 2;
264 *cycleCounter += wait;
265 }
266 return value;
267}
268
269void DS7Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
270 struct DS* ds = (struct DS*) cpu->master;
271 struct DSMemory* memory = &ds->memory;
272 int wait = 0;
273
274 switch (address >> DS_BASE_OFFSET) {
275 default:
276 break;
277 }
278
279 if (cycleCounter) {
280 ++wait;
281 *cycleCounter += wait;
282 }
283}
284
285void DS7Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
286 struct DS* ds = (struct DS*) cpu->master;
287 struct DSMemory* memory = &ds->memory;
288 int wait = 0;
289
290 switch (address >> DS_BASE_OFFSET) {
291 default:
292 break;
293 }
294
295 if (cycleCounter) {
296 ++wait;
297 *cycleCounter += wait;
298 }
299}
300
301void DS7Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
302 struct DS* ds = (struct DS*) cpu->master;
303 struct DSMemory* memory = &ds->memory;
304 int wait = 0;
305
306 switch (address >> DS_BASE_OFFSET) {
307 default:
308 break;
309 }
310
311 if (cycleCounter) {
312 ++wait;
313 *cycleCounter += wait;
314 }
315}
316
317uint32_t DS7LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
318 struct DS* ds = (struct DS*) cpu->master;
319 struct DSMemory* memory = &ds->memory;
320 uint32_t value;
321 int wait = 0;
322
323 int i;
324 int offset = 4;
325 int popcount = 0;
326 if (direction & LSM_D) {
327 offset = -4;
328 popcount = popcount32(mask);
329 address -= (popcount << 2) - 4;
330 }
331
332 if (direction & LSM_B) {
333 address += offset;
334 }
335
336 uint32_t addressMisalign = address & 0x3;
337 address &= 0xFFFFFFFC;
338
339 switch (address >> DS_BASE_OFFSET) {
340 default:
341 break;
342 }
343
344 if (cycleCounter) {
345 ++wait;
346 *cycleCounter += wait;
347 }
348
349 if (direction & LSM_B) {
350 address -= offset;
351 }
352
353 if (direction & LSM_D) {
354 address -= (popcount << 2) + 4;
355 }
356
357 return address | addressMisalign;
358}
359
360
361uint32_t DS7StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
362 struct DS* ds = (struct DS*) cpu->master;
363 struct DSMemory* memory = &ds->memory;
364 uint32_t value;
365 int wait = 0;
366
367 int i;
368 int offset = 4;
369 int popcount = 0;
370 if (direction & LSM_D) {
371 offset = -4;
372 popcount = popcount32(mask);
373 address -= (popcount << 2) - 4;
374 }
375
376 if (direction & LSM_B) {
377 address += offset;
378 }
379
380 uint32_t addressMisalign = address & 0x3;
381 address &= 0xFFFFFFFC;
382
383 switch (address >> DS_BASE_OFFSET) {
384 default:
385 break;
386 }
387
388 if (cycleCounter) {
389 *cycleCounter += wait;
390 }
391
392 if (direction & LSM_B) {
393 address -= offset;
394 }
395
396 if (direction & LSM_D) {
397 address -= (popcount << 2) + 4;
398 }
399
400 return address | addressMisalign;
401}
402
403static void DS9SetActiveRegion(struct ARMCore* cpu, uint32_t address) {
404 struct DS* ds = (struct DS*) cpu->master;
405 struct DSMemory* memory = &ds->memory;
406
407 int newRegion = address >> DS_BASE_OFFSET;
408
409 memory->activeRegion9 = newRegion;
410 switch (newRegion) {
411 case DS9_REGION_ITCM:
412 case DS9_REGION_ITCM_MIRROR:
413 if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) {
414 cpu->memory.activeRegion = memory->itcm;
415 cpu->memory.activeMask = DS9_SIZE_ITCM - 1;
416 return;
417 }
418 goto jump_error;
419 case DS_REGION_RAM:
420 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
421 cpu->memory.activeRegion = memory->ram;
422 cpu->memory.activeMask = DS_SIZE_RAM - 1;
423 return;
424 }
425 goto jump_error;
426 case DS9_REGION_BIOS:
427 // TODO: Mask properly
428 if (memory->bios9) {
429 cpu->memory.activeRegion = memory->bios9;
430 cpu->memory.activeMask = DS9_SIZE_BIOS - 1;
431 } else {
432 cpu->memory.activeRegion = _deadbeef;
433 cpu->memory.activeMask = 0;
434 }
435 return;
436 default:
437 break;
438 }
439
440jump_error:
441 cpu->memory.activeRegion = _deadbeef;
442 cpu->memory.activeMask = 0;
443 mLOG(DS_MEM, FATAL, "Jumped to invalid address: %08X", address);
444}
445
446uint32_t DS9Load32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
447 struct DS* ds = (struct DS*) cpu->master;
448 struct DSMemory* memory = &ds->memory;
449 uint32_t value = 0;
450 int wait = 0;
451
452 switch (address >> DS_BASE_OFFSET) {
453 case DS_REGION_RAM:
454 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
455 LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
456 break;
457 }
458 mLOG(DS_MEM, STUB, "Unimplemented DS9 Load32: %08X", address);
459 break;
460 default:
461 mLOG(DS_MEM, STUB, "Unimplemented DS9 Load32: %08X", address);
462 break;
463 }
464
465 if (cycleCounter) {
466 wait += 2;
467 *cycleCounter += wait;
468 }
469 // Unaligned 32-bit loads are "rotated" so they make some semblance of sense
470 int rotate = (address & 3) << 3;
471 return ROR(value, rotate);
472}
473
474uint32_t DS9Load16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
475 struct DS* ds = (struct DS*) cpu->master;
476 struct DSMemory* memory = &ds->memory;
477 uint32_t value = 0;
478 int wait = 0;
479
480 switch (address >> DS_BASE_OFFSET) {
481 case DS_REGION_RAM:
482 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
483 LOAD_16(value, address & (DS_SIZE_RAM - 1), memory->ram);
484 break;
485 }
486 mLOG(DS_MEM, STUB, "Unimplemented DS9 Load16: %08X", address);
487 default:
488 mLOG(DS_MEM, STUB, "Unimplemented DS9 Load16: %08X", address);
489 break;
490 }
491
492 if (cycleCounter) {
493 wait += 2;
494 *cycleCounter += wait;
495 }
496 // Unaligned 16-bit loads are "unpredictable", TODO: See what DS does
497 int rotate = (address & 1) << 3;
498 return ROR(value, rotate);
499}
500
501uint32_t DS9Load8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
502 struct DS* ds = (struct DS*) cpu->master;
503 struct DSMemory* memory = &ds->memory;
504 uint32_t value = 0;
505 int wait = 0;
506
507 switch (address >> DS_BASE_OFFSET) {
508 case DS_REGION_RAM:
509 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
510 value = ((uint8_t*) memory->ram)[address & (DS_SIZE_RAM - 1)];
511 break;
512 }
513 mLOG(DS_MEM, STUB, "Unimplemented DS9 Load8: %08X", address);
514 default:
515 mLOG(DS_MEM, STUB, "Unimplemented DS9 Load8: %08X", address);
516 break;
517 }
518
519 if (cycleCounter) {
520 wait += 2;
521 *cycleCounter += wait;
522 }
523 return value;
524}
525
526void DS9Store32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter) {
527 struct DS* ds = (struct DS*) cpu->master;
528 struct DSMemory* memory = &ds->memory;
529 int wait = 0;
530
531 switch (address >> DS_BASE_OFFSET) {
532 case DS9_REGION_ITCM:
533 case DS9_REGION_ITCM_MIRROR:
534 if (address < (512 << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) {
535 STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
536 break;
537 }
538 mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value);
539 break;
540 case DS_REGION_RAM:
541 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
542 STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
543 break;
544 }
545 mLOG(DS_MEM, STUB, "Unimplemented DS9 Store32: %08X:%08X", address, value);
546 break;
547 default:
548 mLOG(DS_MEM, STUB, "Unimplemented DS9 Store32: %08X:%08X", address, value);
549 break;
550 }
551
552 if (cycleCounter) {
553 ++wait;
554 *cycleCounter += wait;
555 }
556}
557
558void DS9Store16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter) {
559 struct DS* ds = (struct DS*) cpu->master;
560 struct DSMemory* memory = &ds->memory;
561 int wait = 0;
562
563 switch (address >> DS_BASE_OFFSET) {
564 case DS9_REGION_ITCM:
565 case DS9_REGION_ITCM_MIRROR:
566 if (address < (512 << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) {
567 STORE_16(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
568 break;
569 }
570 mLOG(DS_MEM, STUB, "Bad DS9 Store16: %08X:%04X", address, value);
571 break;
572 case DS_REGION_RAM:
573 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
574 STORE_16(value, address & (DS_SIZE_RAM - 1), memory->ram);
575 break;
576 }
577 mLOG(DS_MEM, STUB, "Unimplemented DS9 Store16: %08X:%04X", address, value);
578 break;
579 default:
580 mLOG(DS_MEM, STUB, "Unimplemented DS9 Store16: %08X:%04X", address, value);
581 break;
582 }
583
584 if (cycleCounter) {
585 ++wait;
586 *cycleCounter += wait;
587 }
588}
589
590void DS9Store8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter) {
591 struct DS* ds = (struct DS*) cpu->master;
592 struct DSMemory* memory = &ds->memory;
593 int wait = 0;
594
595 switch (address >> DS_BASE_OFFSET) {
596 case DS9_REGION_ITCM:
597 case DS9_REGION_ITCM_MIRROR:
598 if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) {
599 ((uint8_t*) memory->itcm)[address & (DS9_SIZE_ITCM - 1)] = value;
600 break;
601 }
602 mLOG(DS_MEM, STUB, "Bad DS9 Store8: %08X:%02X", address, value);
603 break;
604 case DS_REGION_RAM:
605 if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
606 ((uint8_t*) memory->ram)[address & (DS_SIZE_RAM - 1)] = value;
607 break;
608 }
609 mLOG(DS_MEM, STUB, "Unimplemented DS9 Store8: %08X:%02X", address, value);
610 default:
611 mLOG(DS_MEM, STUB, "Unimplemented DS9 Store8: %08X:%02X", address, value);
612 break;
613 }
614
615 if (cycleCounter) {
616 ++wait;
617 *cycleCounter += wait;
618 }
619}
620
621uint32_t DS9LoadMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
622 struct DS* ds = (struct DS*) cpu->master;
623 struct DSMemory* memory = &ds->memory;
624 uint32_t value;
625 int wait = 0;
626
627 int i;
628 int offset = 4;
629 int popcount = 0;
630 if (direction & LSM_D) {
631 offset = -4;
632 popcount = popcount32(mask);
633 address -= (popcount << 2) - 4;
634 }
635
636 if (direction & LSM_B) {
637 address += offset;
638 }
639
640 uint32_t addressMisalign = address & 0x3;
641 address &= 0xFFFFFFFC;
642
643 switch (address >> DS_BASE_OFFSET) {
644 case DS_REGION_RAM:
645 LDM_LOOP(if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
646 LOAD_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
647 } else {
648 mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address);
649 });
650 break;
651 default:
652 mLOG(DS_MEM, STUB, "Unimplemented DS9 LDM: %08X", address);
653 LDM_LOOP(value = 0);
654 break;
655 }
656
657 if (cycleCounter) {
658 ++wait;
659 *cycleCounter += wait;
660 }
661
662 if (direction & LSM_B) {
663 address -= offset;
664 }
665
666 if (direction & LSM_D) {
667 address -= (popcount << 2) + 4;
668 }
669
670 return address | addressMisalign;
671}
672
673
674uint32_t DS9StoreMultiple(struct ARMCore* cpu, uint32_t address, int mask, enum LSMDirection direction, int* cycleCounter) {
675 struct DS* ds = (struct DS*) cpu->master;
676 struct DSMemory* memory = &ds->memory;
677 uint32_t value;
678 int wait = 0;
679
680 int i;
681 int offset = 4;
682 int popcount = 0;
683 if (direction & LSM_D) {
684 offset = -4;
685 popcount = popcount32(mask);
686 address -= (popcount << 2) - 4;
687 }
688
689 if (direction & LSM_B) {
690 address += offset;
691 }
692
693 uint32_t addressMisalign = address & 0x3;
694 address &= 0xFFFFFFFC;
695
696 switch (address >> DS_BASE_OFFSET) {
697 case DS9_REGION_ITCM:
698 case DS9_REGION_ITCM_MIRROR:
699 STM_LOOP(if (address < (512U << ARMTCMControlGetVirtualSize(cpu->cp15.r9.i))) {
700 STORE_32(value, address & (DS9_SIZE_ITCM - 1), memory->itcm);
701 } else {
702 mLOG(DS_MEM, STUB, "Bad DS9 Store32: %08X:%08X", address, value);
703 });
704 break;
705 case DS_REGION_RAM:
706 STM_LOOP(if ((address & (DS_SIZE_RAM - 1)) < DS_SIZE_RAM) {
707 STORE_32(value, address & (DS_SIZE_RAM - 1), memory->ram);
708 } else {
709 mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
710 });
711 break;
712 default:
713 mLOG(DS_MEM, STUB, "Unimplemented DS9 STM: %08X", address);
714 STM_LOOP();
715 break;
716 }
717
718 if (cycleCounter) {
719 *cycleCounter += wait;
720 }
721
722 if (direction & LSM_B) {
723 address -= offset;
724 }
725
726 if (direction & LSM_D) {
727 address -= (popcount << 2) + 4;
728 }
729
730 return address | addressMisalign;
731}
732
733int32_t DSMemoryStall(struct ARMCore* cpu, int32_t wait) {
734 return wait;
735}
736