update gpu DMA related code to pcsxr-svn Nov 28
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 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
f95a77f7 8#include <stdio.h>
9
10#include "emu_if.h"
7e605697 11#include "pcsxmem.h"
7139f3c8 12#include "../psxhle.h"
d28b54b1 13#include "../r3000a.h"
52082bc1 14#include "../cdrom.h"
15#include "../psxdma.h"
16#include "../mdec.h"
7139f3c8 17
ae602c19 18#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
19
7139f3c8 20//#define evprintf printf
21#define evprintf(...)
22
f95a77f7 23char invalid_code[0x100000];
d28b54b1 24u32 event_cycles[PSXINT_COUNT];
f95a77f7 25
654e8cfb 26static void schedule_timeslice(void)
f95a77f7 27{
654e8cfb 28 u32 i, c = psxRegs.cycle;
29 s32 min, dif;
30
31 min = psxNextsCounter + psxNextCounter - c;
32 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
33 dif = event_cycles[i] - c;
34 //evprintf(" ev %d\n", dif);
35 if (0 < dif && dif < min)
36 min = dif;
37 }
38 next_interupt = c + min;
39
40#if 0
41 static u32 cnt, last_cycle;
42 static u64 sum;
43 if (last_cycle) {
44 cnt++;
45 sum += psxRegs.cycle - last_cycle;
46 if ((cnt & 0xff) == 0)
47 printf("%u\n", (u32)(sum / cnt));
48 }
49 last_cycle = psxRegs.cycle;
50#endif
51}
ae602c19 52
52082bc1 53typedef void (irq_func)();
54
55static irq_func * const irq_funcs[] = {
56 [PSXINT_SIO] = sioInterrupt,
57 [PSXINT_CDR] = cdrInterrupt,
58 [PSXINT_CDREAD] = cdrReadInterrupt,
59 [PSXINT_GPUDMA] = gpuInterrupt,
60 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
61 [PSXINT_SPUDMA] = spuInterrupt,
528ad661 62 [PSXINT_MDECINDMA] = mdec0Interrupt,
57a757ce 63 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
52082bc1 64};
65
66/* local dupe of psxBranchTest, using event_cycles */
67static void irq_test(void)
68{
69 u32 irqs = psxRegs.interrupt;
70 u32 cycle = psxRegs.cycle;
71 u32 irq, irq_bits;
72
73 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
74 psxRcntUpdate();
75
76 // irq_funcs() may queue more irqs
77 psxRegs.interrupt = 0;
78
79 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
80 if (!(irq_bits & 1))
81 continue;
82 if ((s32)(cycle - event_cycles[irq]) >= 0) {
83 irqs &= ~(1 << irq);
84 irq_funcs[irq]();
85 }
86 }
87 psxRegs.interrupt |= irqs;
88
89 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
90 psxException(0x400, 0);
91 pending_exception = 1;
92 }
93}
94
654e8cfb 95void gen_interupt()
96{
654e8cfb 97 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 98#ifdef DRC_DBG
99 psxRegs.cycle += 2;
7139f3c8 100#endif
101
52082bc1 102 irq_test();
103 //psxBranchTest();
104 //pending_exception = 1;
7139f3c8 105
654e8cfb 106 schedule_timeslice();
ae602c19 107
654e8cfb 108 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
109 next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 110}
111
28bc5688 112void MTC0_()
113{
114 extern void psxMTC0();
115
116 evprintf("ari64 MTC0 %08x %08x %u\n", psxRegs.code, psxRegs.pc, psxRegs.cycle);
117 psxMTC0();
118 gen_interupt(); /* FIXME: checking pending irqs should be enough */
119}
120
f95a77f7 121void check_interupt()
122{
52082bc1 123 /* FIXME (also asm) */
7139f3c8 124 printf("ari64_check_interupt\n");
f95a77f7 125}
126
52082bc1 127void new_dyna_save(void)
128{
129 // psxRegs.intCycle is always maintained, no need to convert
130}
131
132void new_dyna_restore(void)
133{
134 int i;
135 for (i = 0; i < PSXINT_NEWDRC_CHECK; i++)
136 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
137}
138
b9b61529 139void *gte_handlers[64];
140
141/* from gte.txt.. not sure if this is any good. */
142const char gte_cycletab[64] = {
143 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
144 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
145 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
146 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
147 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
148};
f95a77f7 149
150static int ari64_init()
151{
b9b61529 152 extern void (*psxCP2[64])();
153 extern void psxNULL();
7e605697 154 extern void *psxH_ptr;
f95a77f7 155 size_t i;
b9b61529 156
f95a77f7 157 new_dynarec_init();
7e605697 158 new_dyna_pcsx_mem_init();
7139f3c8 159
ae602c19 160 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 161 if (psxCP2[i] != psxNULL)
162 gte_handlers[i] = psxCP2[i];
163
7e605697 164 psxH_ptr = psxH;
165
b9b61529 166 return 0;
f95a77f7 167}
168
169static void ari64_reset()
170{
f95a77f7 171 printf("ari64_reset\n");
7e605697 172 new_dyna_pcsx_mem_reset();
4b421010 173 invalidate_all_pages();
174 pending_exception = 1;
f95a77f7 175}
176
177static void ari64_execute()
178{
654e8cfb 179 schedule_timeslice();
180
181 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
182 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 183
b9b61529 184 new_dyna_start();
654e8cfb 185
186 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
187 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 188}
189
4b421010 190static void ari64_clear(u32 addr, u32 size)
f95a77f7 191{
4b421010 192 u32 start, end;
193
194 evprintf("ari64_clear %08x %04x\n", addr, size);
195
196 /* check for RAM mirrors */
4cb76aa4 197 if ((addr & ~0xe0600000) < 0x200000) {
198 addr &= ~0xe0600000;
f76eeef9 199 addr |= 0x80000000;
4b421010 200 }
201
202 start = addr >> 12;
203 end = (addr + size) >> 12;
204
205 for (; start <= end; start++)
206 if (!invalid_code[start])
207 invalidate_block(start);
f95a77f7 208}
209
210static void ari64_shutdown()
211{
212 new_dynarec_cleanup();
213}
214
7139f3c8 215extern void intExecute();
216extern void intExecuteT();
217extern void intExecuteBlock();
218extern void intExecuteBlockT();
219#ifndef DRC_DBG
220#define intExecuteT intExecute
221#define intExecuteBlockT intExecuteBlock
222#endif
223
f95a77f7 224R3000Acpu psxRec = {
225 ari64_init,
226 ari64_reset,
7139f3c8 227#if 1
f95a77f7 228 ari64_execute,
7139f3c8 229 ari64_execute,
230#else
231 intExecuteT,
232 intExecuteBlockT,
233#endif
f95a77f7 234 ari64_clear,
235 ari64_shutdown
236};
7139f3c8 237
238// TODO: rm
239#ifndef DRC_DBG
240void do_insn_trace() {}
241void do_insn_cmp() {}
242#endif
243
244#if defined(__x86_64__) || defined(__i386__)
245unsigned int address, readmem_word, word;
246unsigned short hword;
247unsigned char byte;
ccf51908 248int pending_exception, stop;
7139f3c8 249unsigned int next_interupt;
7e605697 250void *psxH_ptr;
7139f3c8 251void new_dynarec_init() {}
3eb78778 252void new_dyna_start() {}
7139f3c8 253void new_dynarec_cleanup() {}
ccf51908 254void invalidate_all_pages() {}
255void invalidate_block(unsigned int block) {}
7e605697 256void new_dyna_pcsx_mem_init(void) {}
257void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 258#endif
259
260#ifdef DRC_DBG
261
262#include <stddef.h>
263static FILE *f;
264extern u32 last_io_addr;
265
266static void dump_mem(const char *fname, void *mem, size_t size)
267{
268 FILE *f1 = fopen(fname, "wb");
3eb78778 269 if (f1 == NULL)
270 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 271 fwrite(mem, 1, size, f1);
272 fclose(f1);
273}
274
275void do_insn_trace(void)
276{
277 static psxRegisters oldregs;
278 static u32 old_io_addr = (u32)-1;
279 static u32 old_io_data = 0xbad0c0de;
280 u32 *allregs_p = (void *)&psxRegs;
281 u32 *allregs_o = (void *)&oldregs;
282 u32 *io_data;
283 int i;
284 u8 byte;
285
286//last_io_addr = 0x5e2c8;
287 if (f == NULL)
288 f = fopen("tracelog", "wb");
289
290 oldregs.code = psxRegs.code; // don't care
291 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
292 if (allregs_p[i] != allregs_o[i]) {
293 fwrite(&i, 1, 1, f);
294 fwrite(&allregs_p[i], 1, 4, f);
295 allregs_o[i] = allregs_p[i];
296 }
297 }
298 if (old_io_addr != last_io_addr) {
299 byte = 0xfd;
300 fwrite(&byte, 1, 1, f);
301 fwrite(&last_io_addr, 1, 4, f);
302 old_io_addr = last_io_addr;
303 }
304 io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
305 if (old_io_data != *io_data) {
306 byte = 0xfe;
307 fwrite(&byte, 1, 1, f);
308 fwrite(io_data, 1, 4, f);
309 old_io_data = *io_data;
310 }
311 byte = 0xff;
312 fwrite(&byte, 1, 1, f);
313
314#if 0
315 if (psxRegs.cycle == 190230) {
316 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
317 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
318 printf("dumped\n");
319 exit(1);
320 }
321#endif
322}
323
324static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
325 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
326 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
327 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
328 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
329 "lo", "hi",
330 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
331 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
332 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
333 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
334
335 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
336 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
337 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
338 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
339
340 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
341 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
342 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
343 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
344
345 "PC", "code", "cycle", "interrupt",
346};
347
3eb78778 348static struct {
349 int reg;
350 u32 val, val_expect;
351 u32 pc, cycle;
352} miss_log[64];
353static int miss_log_i;
354#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
355#define miss_log_mask (miss_log_len-1)
356
357static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
358{
359 miss_log[miss_log_i].reg = reg;
360 miss_log[miss_log_i].val = val;
361 miss_log[miss_log_i].val_expect = val_expect;
362 miss_log[miss_log_i].pc = pc;
363 miss_log[miss_log_i].cycle = cycle;
364 miss_log_i = (miss_log_i + 1) & miss_log_mask;
365}
366
7139f3c8 367void breakme() {}
368
369void do_insn_cmp(void)
370{
371 static psxRegisters rregs;
372 static u32 mem_addr, mem_val;
373 u32 *allregs_p = (void *)&psxRegs;
374 u32 *allregs_e = (void *)&rregs;
375 static u32 ppc, failcount;
376 int i, ret, bad = 0;
377 u8 code;
378
379 if (f == NULL)
380 f = fopen("tracelog", "rb");
381
382 while (1) {
383 if ((ret = fread(&code, 1, 1, f)) <= 0)
384 break;
385 if (ret <= 0)
386 break;
387 if (code == 0xff)
388 break;
389 if (code == 0xfd) {
390 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
391 break;
392 continue;
393 }
394 if (code == 0xfe) {
395 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
396 break;
397 continue;
398 }
399 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
400 break;
401 }
402
403 if (ret <= 0) {
404 printf("EOF?\n");
405 goto end;
406 }
407
408 psxRegs.code = rregs.code; // don't care
409psxRegs.cycle = rregs.cycle;
410psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
411
412//if (psxRegs.cycle == 166172) breakme();
413//if (psxRegs.cycle > 11296376) printf("pc=%08x %u %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
414
415 mem_addr &= 0x1ffffc;
416
417 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
418 mem_val == *(u32 *)(psxM + mem_addr)
419 ) {
420 failcount = 0;
421 goto ok;
422 }
423
424 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
425 if (allregs_p[i] != allregs_e[i]) {
3eb78778 426 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 427 bad++;
428 }
429 }
430
431 if (mem_val != *(u32 *)(psxM + mem_addr)) {
432 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
433 goto end;
434 }
435
436 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 437 static int last_mcycle;
438 if (last_mcycle != psxRegs.cycle >> 20) {
439 printf("%u\n", psxRegs.cycle);
440 last_mcycle = psxRegs.cycle >> 20;
441 }
7139f3c8 442 failcount++;
443 goto ok;
444 }
445
446end:
3eb78778 447 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
448 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
449 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
450 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
451 printf("-- %d\n", bad);
452 for (i = 0; i < 8; i++)
453 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 454 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 455 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
456 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
457 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
458 exit(1);
459ok:
460 psxRegs.cycle = rregs.cycle + 2; // sync timing
461 ppc = psxRegs.pc;
462}
463
464#endif