drc: merge Ari64's patch: 11_reduce_invstub_memory_usage
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / pcsxmem.c
1 /*
2  * (C) GraÅžvydas "notaz" Ignotas, 2010
3  *
4  * This work is licensed under the terms of GNU GPL version 2 or later.
5  * See the COPYING file in the top-level directory.
6  */
7
8 #include <stdio.h>
9 #include "../psxhw.h"
10 #include "../cdrom.h"
11 #include "../mdec.h"
12 #include "emu_if.h"
13 #include "pcsxmem.h"
14
15 //#define memprintf printf
16 #define memprintf(...)
17
18 static int ram_is_ro;
19
20 static void read_mem8()
21 {
22         memprintf("ari64_read_mem8  %08x @%08x %u\n", address, psxRegs.pc, psxRegs.cycle);
23         readmem_word = psxMemRead8(address) & 0xff;
24 }
25
26 static void read_mem16()
27 {
28         memprintf("ari64_read_mem16 %08x @%08x %u\n", address, psxRegs.pc, psxRegs.cycle);
29         readmem_word = psxMemRead16(address) & 0xffff;
30 }
31
32 static void read_mem32()
33 {
34         memprintf("ari64_read_mem32 %08x @%08x %u\n", address, psxRegs.pc, psxRegs.cycle);
35         readmem_word = psxMemRead32(address);
36 }
37
38 static void write_mem8()
39 {
40         memprintf("ari64_write_mem8  %08x,       %02x @%08x %u\n", address, byte, psxRegs.pc, psxRegs.cycle);
41         psxMemWrite8(address, byte);
42 }
43
44 static void write_mem16()
45 {
46         memprintf("ari64_write_mem16 %08x,     %04x @%08x %u\n", address, hword, psxRegs.pc, psxRegs.cycle);
47         psxMemWrite16(address, hword);
48 }
49
50 static void write_mem32()
51 {
52         memprintf("ari64_write_mem32 %08x, %08x @%08x %u\n", address, word, psxRegs.pc, psxRegs.cycle);
53         psxMemWrite32(address, word);
54 }
55
56 static void read_mem_dummy()
57 {
58         readmem_word = 0;
59 }
60
61 static void write_mem_dummy()
62 {
63 }
64
65 extern void ari_read_ram8();
66 extern void ari_read_ram16();
67 extern void ari_read_ram32();
68 extern void ari_read_ram_mirror8();
69 extern void ari_read_ram_mirror16();
70 extern void ari_read_ram_mirror32();
71 extern void ari_write_ram8();
72 extern void ari_write_ram16();
73 extern void ari_write_ram32();
74 extern void ari_write_ram_mirror8();
75 extern void ari_write_ram_mirror16();
76 extern void ari_write_ram_mirror32();
77 extern void ari_read_bios8();
78 extern void ari_read_bios16();
79 extern void ari_read_bios32();
80 extern void ari_read_io8();
81 extern void ari_read_io16();
82 extern void ari_read_io32();
83 extern void ari_write_io8();
84 extern void ari_write_io16();
85 extern void ari_write_io32();
86
87 void (*readmem[0x10000])();
88 void (*readmemb[0x10000])();
89 void (*readmemh[0x10000])();
90 void (*writemem[0x10000])();
91 void (*writememb[0x10000])();
92 void (*writememh[0x10000])();
93
94 static void write_mem_check_ro32()
95 {
96         if (!ram_is_ro)
97                 *(u32 *)(address | 0x80000000) = word;
98 }
99
100 static void write_biu()
101 {
102         memprintf("write_biu %08x, %08x @%08x %u\n", address, word, psxRegs.pc, psxRegs.cycle);
103
104         if (address != 0xfffe0130)
105                 return;
106
107         switch (word) {
108         case 0x800: case 0x804:
109                 ram_is_ro = 1;
110                 break;
111         case 0: case 0x1e988:
112                 ram_is_ro = 0;
113                 break;
114         default:
115                 memprintf("write_biu: unexpected val: %08x\n", word);
116                 break;
117         }
118 }
119
120 /* IO handlers */
121 static u32 io_read_sio16()
122 {
123         return sioRead8() | (sioRead8() << 8);
124 }
125
126 static u32 io_read_sio32()
127 {
128         return sioRead8() | (sioRead8() << 8) | (sioRead8() << 16) | (sioRead8() << 24);
129 }
130
131 static void io_write_sio16(u32 value)
132 {
133         sioWrite8((unsigned char)value);
134         sioWrite8((unsigned char)(value>>8));
135 }
136
137 static void io_write_sio32(u32 value)
138 {
139         sioWrite8((unsigned char)value);
140         sioWrite8((unsigned char)((value&0xff) >>  8));
141         sioWrite8((unsigned char)((value&0xff) >> 16));
142         sioWrite8((unsigned char)((value&0xff) >> 24));
143 }
144
145 #define make_rcnt_funcs(i) \
146 static u32 io_rcnt_read_count##i()  { return psxRcntRcount(i); } \
147 static u32 io_rcnt_read_mode##i()   { return psxRcntRmode(i); } \
148 static u32 io_rcnt_read_target##i() { return psxRcntRtarget(i); } \
149 static void io_rcnt_write_count##i(u32 val)  { psxRcntWcount(i, val & 0xffff); } \
150 static void io_rcnt_write_mode##i(u32 val)   { psxRcntWmode(i, val); } \
151 static void io_rcnt_write_target##i(u32 val) { psxRcntWtarget(i, val & 0xffff); }
152
153 make_rcnt_funcs(0)
154 make_rcnt_funcs(1)
155 make_rcnt_funcs(2)
156
157 static void io_write_ireg16(u32 value)
158 {
159         if (Config.Sio) psxHu16ref(0x1070) |= 0x80;
160         if (Config.SpuIrq) psxHu16ref(0x1070) |= 0x200;
161         psxHu16ref(0x1070) &= psxHu16(0x1074) & value;
162 }
163
164 static void io_write_imask16(u32 value)
165 {
166         psxHu16ref(0x1074) = value;
167         if (psxHu16ref(0x1070) & value)
168                 new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
169 }
170
171 static void io_write_ireg32(u32 value)
172 {
173         if (Config.Sio) psxHu32ref(0x1070) |= 0x80;
174         if (Config.SpuIrq) psxHu32ref(0x1070) |= 0x200;
175         psxHu32ref(0x1070) &= psxHu32(0x1074) & value;
176 }
177
178 static void io_write_imask32(u32 value)
179 {
180         psxHu32ref(0x1074) = value;
181         if (psxHu32ref(0x1070) & value)
182                 new_dyna_set_event(PSXINT_NEWDRC_CHECK, 1);
183 }
184
185 static void io_write_dma_icr32(u32 value)
186 {
187         u32 tmp = ~value & HW_DMA_ICR;
188         HW_DMA_ICR = ((tmp ^ value) & 0xffffff) ^ tmp;
189 }
190
191 #define make_dma_func(n) \
192 static void io_write_chcr##n(u32 value) \
193 { \
194         HW_DMA##n##_CHCR = value; \
195         if (value & 0x01000000 && HW_DMA_PCR & (8 << (n * 4))) { \
196                 psxDma##n(HW_DMA##n##_MADR, HW_DMA##n##_BCR, value); \
197         } \
198 }
199
200 make_dma_func(0)
201 make_dma_func(1)
202 make_dma_func(2)
203 make_dma_func(3)
204 make_dma_func(4)
205 make_dma_func(6)
206
207 /* IO tables for 1000-1880 */
208 #define IOADR8(a)  ((a) & 0xfff)
209 #define IOADR16(a) (((a) & 0xfff) >> 1)
210 #define IOADR32(a) (((a) & 0xfff) >> 2)
211
212 static const void *io_read8 [0x880] = {
213         [IOADR8(0x1040)] = sioRead8,
214         [IOADR8(0x1800)] = cdrRead0,
215         [IOADR8(0x1801)] = cdrRead1,
216         [IOADR8(0x1802)] = cdrRead2,
217         [IOADR8(0x1803)] = cdrRead3,
218 };
219 static const void *io_read16[0x880/2] = {
220         [IOADR16(0x1040)] = io_read_sio16,
221         [IOADR16(0x1044)] = sioReadStat16,
222         [IOADR16(0x1048)] = sioReadMode16,
223         [IOADR16(0x104a)] = sioReadCtrl16,
224         [IOADR16(0x104e)] = sioReadBaud16,
225         [IOADR16(0x1100)] = io_rcnt_read_count0,
226         [IOADR16(0x1104)] = io_rcnt_read_mode0,
227         [IOADR16(0x1108)] = io_rcnt_read_target0,
228         [IOADR16(0x1110)] = io_rcnt_read_count1,
229         [IOADR16(0x1114)] = io_rcnt_read_mode1,
230         [IOADR16(0x1118)] = io_rcnt_read_target1,
231         [IOADR16(0x1120)] = io_rcnt_read_count2,
232         [IOADR16(0x1124)] = io_rcnt_read_mode2,
233         [IOADR16(0x1128)] = io_rcnt_read_target2,
234 };
235 static const void *io_read32[0x880/4] = {
236         [IOADR32(0x1040)] = io_read_sio32,
237         [IOADR32(0x1100)] = io_rcnt_read_count0,
238         [IOADR32(0x1104)] = io_rcnt_read_mode0,
239         [IOADR32(0x1108)] = io_rcnt_read_target0,
240         [IOADR32(0x1110)] = io_rcnt_read_count1,
241         [IOADR32(0x1114)] = io_rcnt_read_mode1,
242         [IOADR32(0x1118)] = io_rcnt_read_target1,
243         [IOADR32(0x1120)] = io_rcnt_read_count2,
244         [IOADR32(0x1124)] = io_rcnt_read_mode2,
245         [IOADR32(0x1128)] = io_rcnt_read_target2,
246 //      [IOADR32(0x1810)] = GPU_readData,
247 //      [IOADR32(0x1814)] = GPU_readStatus,
248         [IOADR32(0x1820)] = mdecRead0,
249         [IOADR32(0x1824)] = mdecRead1,
250 };
251 // write(u32 val)
252 static const void *io_write8 [0x880] = {
253         [IOADR8(0x1040)] = sioWrite8,
254         [IOADR8(0x1800)] = cdrWrite0,
255         [IOADR8(0x1801)] = cdrWrite1,
256         [IOADR8(0x1802)] = cdrWrite2,
257         [IOADR8(0x1803)] = cdrWrite3,
258 };
259 static const void *io_write16[0x880/2] = {
260         [IOADR16(0x1040)] = io_write_sio16,
261         [IOADR16(0x1044)] = sioWriteStat16,
262         [IOADR16(0x1048)] = sioWriteMode16,
263         [IOADR16(0x104a)] = sioWriteCtrl16,
264         [IOADR16(0x104e)] = sioWriteBaud16,
265         [IOADR16(0x1070)] = io_write_ireg16,
266         [IOADR16(0x1074)] = io_write_imask16,
267         [IOADR16(0x1100)] = io_rcnt_write_count0,
268         [IOADR16(0x1104)] = io_rcnt_write_mode0,
269         [IOADR16(0x1108)] = io_rcnt_write_target0,
270         [IOADR16(0x1110)] = io_rcnt_write_count1,
271         [IOADR16(0x1114)] = io_rcnt_write_mode1,
272         [IOADR16(0x1118)] = io_rcnt_write_target1,
273         [IOADR16(0x1120)] = io_rcnt_write_count2,
274         [IOADR16(0x1124)] = io_rcnt_write_mode2,
275         [IOADR16(0x1128)] = io_rcnt_write_target2,
276 };
277 static const void *io_write32[0x880/4] = {
278         [IOADR32(0x1040)] = io_write_sio32,
279         [IOADR32(0x1070)] = io_write_ireg32,
280         [IOADR32(0x1074)] = io_write_imask32,
281         [IOADR32(0x1088)] = io_write_chcr0,
282         [IOADR32(0x1098)] = io_write_chcr1,
283         [IOADR32(0x10a8)] = io_write_chcr2,
284         [IOADR32(0x10b8)] = io_write_chcr3,
285         [IOADR32(0x10c8)] = io_write_chcr4,
286         [IOADR32(0x10e8)] = io_write_chcr6,
287         [IOADR32(0x10f4)] = io_write_dma_icr32,
288         [IOADR32(0x1100)] = io_rcnt_write_count0,
289         [IOADR32(0x1104)] = io_rcnt_write_mode0,
290         [IOADR32(0x1108)] = io_rcnt_write_target0,
291         [IOADR32(0x1110)] = io_rcnt_write_count1,
292         [IOADR32(0x1114)] = io_rcnt_write_mode1,
293         [IOADR32(0x1118)] = io_rcnt_write_target1,
294         [IOADR32(0x1120)] = io_rcnt_write_count2,
295         [IOADR32(0x1124)] = io_rcnt_write_mode2,
296         [IOADR32(0x1128)] = io_rcnt_write_target2,
297 //      [IOADR32(0x1810)] = GPU_writeData,
298 //      [IOADR32(0x1814)] = GPU_writeStatus,
299         [IOADR32(0x1820)] = mdecWrite0,
300         [IOADR32(0x1824)] = mdecWrite1,
301 };
302
303 // this has to be in .bss to link into dynarec_local
304 struct {
305         void *tab_read8;
306         void *tab_read16;
307         void *tab_read32;
308         void *tab_write8;
309         void *tab_write16;
310         void *tab_write32;
311         void *spu_readf;
312         void *spu_writef;
313 } nd_pcsx_io;
314
315 void new_dyna_pcsx_mem_init(void)
316 {
317         int i;
318
319         // default/unmapped handlers
320         for (i = 0; i < 0x10000; i++) {
321                 readmemb[i] = read_mem8;
322                 readmemh[i] = read_mem16;
323                 readmem[i] = read_mem32;
324                 writememb[i] = write_mem8;
325                 writememh[i] = write_mem16;
326                 writemem[i] = write_mem32;
327 #if 1
328                 readmemb[i] = readmemh[i] = readmem[i] = read_mem_dummy;
329                 writememb[i] = writememh[i] = writemem[i] = write_mem_dummy;
330 #endif
331         }
332
333 #if 1
334         // RAM mirrors
335         for (i = 0; i < 0x80; i++) {
336                 readmemb[i] = readmemb[0x8000|i] = readmemb[0xa000|i] = ari_read_ram_mirror8;
337                 readmemh[i] = readmemh[0x8000|i] = readmemh[0xa000|i] = ari_read_ram_mirror16;
338                 readmem[i]  = readmem [0x8000|i] = readmem [0xa000|i] = ari_read_ram_mirror32;
339                 writememb[i] = writememb[0x8000|i] = writememb[0xa000|i] = ari_write_ram_mirror8;
340                 writememh[i] = writememh[0x8000|i] = writememh[0xa000|i] = ari_write_ram_mirror16;
341                 writemem[i]  = writemem [0x8000|i] = writemem [0xa000|i] = ari_write_ram_mirror32;
342         }
343
344         // stupid BIOS RAM check
345         writemem[0] = write_mem_check_ro32;
346         ram_is_ro = 0;
347
348         // RAM direct
349         for (i = 0x8000; i < 0x8020; i++) {
350                 readmemb[i] = ari_read_ram8;
351                 readmemh[i] = ari_read_ram16;
352                 readmem[i] = ari_read_ram32;
353         }
354
355         // BIOS and it's mirrors
356         for (i = 0x1fc0; i < 0x1fc8; i++) {
357                 readmemb[i] = readmemb[0x8000|i] = readmemb[0xa000|i] = ari_read_bios8;
358                 readmemh[i] = readmemh[0x8000|i] = readmemh[0xa000|i] = ari_read_bios16;
359                 readmem[i]  = readmem[0x8000|i]  = readmem[0xa000|i]  = ari_read_bios32;
360         }
361
362         // I/O
363         readmemb[0x1f80] = ari_read_io8;
364         readmemh[0x1f80] = ari_read_io16;
365         readmem[0x1f80]  = ari_read_io32;
366         writememb[0x1f80] = ari_write_io8;
367         writememh[0x1f80] = ari_write_io16;
368         writemem[0x1f80]  = ari_write_io32;
369
370         writemem[0xfffe] = write_biu;
371 #endif
372
373         // fill IO tables
374         nd_pcsx_io.tab_read8 = io_read8;
375         nd_pcsx_io.tab_read16 = io_read16;
376         nd_pcsx_io.tab_read32 = io_read32;
377         nd_pcsx_io.tab_write8 = io_write8;
378         nd_pcsx_io.tab_write16 = io_write16;
379         nd_pcsx_io.tab_write32 = io_write32;
380 }
381
382 void new_dyna_pcsx_mem_reset(void)
383 {
384         // plugins might change so update the pointers
385         nd_pcsx_io.spu_readf = SPU_readRegister;
386         nd_pcsx_io.spu_writef = SPU_writeRegister;
387
388         io_read32[IOADR32(0x1810)] = GPU_readData;
389         io_read32[IOADR32(0x1814)] = GPU_readStatus;
390         io_write32[IOADR32(0x1810)] = GPU_writeData;
391         io_write32[IOADR32(0x1814)] = GPU_writeStatus;
392 }
393