drc: remove some old inline memhandlers
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
... / ...
CommitLineData
1/*
2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
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
10#include "emu_if.h"
11#include "pcsxmem.h"
12#include "../psxhle.h"
13#include "../r3000a.h"
14#include "../cdrom.h"
15#include "../psxdma.h"
16#include "../mdec.h"
17#include "../gte_arm.h"
18#include "../gte_neon.h"
19#define FLAGLESS
20#include "../gte.h"
21
22#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
23
24//#define evprintf printf
25#define evprintf(...)
26
27char invalid_code[0x100000];
28u32 event_cycles[PSXINT_COUNT];
29
30static void schedule_timeslice(void)
31{
32 u32 i, c = psxRegs.cycle;
33 s32 min, dif;
34
35 min = psxNextsCounter + psxNextCounter - c;
36 for (i = 0; i < ARRAY_SIZE(event_cycles); i++) {
37 dif = event_cycles[i] - c;
38 //evprintf(" ev %d\n", dif);
39 if (0 < dif && dif < min)
40 min = dif;
41 }
42 next_interupt = c + min;
43
44#if 0
45 static u32 cnt, last_cycle;
46 static u64 sum;
47 if (last_cycle) {
48 cnt++;
49 sum += psxRegs.cycle - last_cycle;
50 if ((cnt & 0xff) == 0)
51 printf("%u\n", (u32)(sum / cnt));
52 }
53 last_cycle = psxRegs.cycle;
54#endif
55}
56
57typedef void (irq_func)();
58
59static irq_func * const irq_funcs[] = {
60 [PSXINT_SIO] = sioInterrupt,
61 [PSXINT_CDR] = cdrInterrupt,
62 [PSXINT_CDREAD] = cdrReadInterrupt,
63 [PSXINT_GPUDMA] = gpuInterrupt,
64 [PSXINT_MDECOUTDMA] = mdec1Interrupt,
65 [PSXINT_SPUDMA] = spuInterrupt,
66 [PSXINT_MDECINDMA] = mdec0Interrupt,
67 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
68 [PSXINT_CDRDMA] = cdrDmaInterrupt,
69 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
70 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
71};
72
73/* local dupe of psxBranchTest, using event_cycles */
74static void irq_test(void)
75{
76 u32 irqs = psxRegs.interrupt;
77 u32 cycle = psxRegs.cycle;
78 u32 irq, irq_bits;
79
80 if ((psxRegs.cycle - psxNextsCounter) >= psxNextCounter)
81 psxRcntUpdate();
82
83 // irq_funcs() may queue more irqs
84 psxRegs.interrupt = 0;
85
86 for (irq = 0, irq_bits = irqs; irq_bits != 0; irq++, irq_bits >>= 1) {
87 if (!(irq_bits & 1))
88 continue;
89 if ((s32)(cycle - event_cycles[irq]) >= 0) {
90 irqs &= ~(1 << irq);
91 irq_funcs[irq]();
92 }
93 }
94 psxRegs.interrupt |= irqs;
95
96 if ((psxHu32(0x1070) & psxHu32(0x1074)) && (Status & 0x401) == 0x401) {
97 psxException(0x400, 0);
98 pending_exception = 1;
99 }
100}
101
102void gen_interupt()
103{
104 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
105
106 irq_test();
107 //psxBranchTest();
108 //pending_exception = 1;
109
110 schedule_timeslice();
111
112 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
113 next_interupt, next_interupt - psxRegs.cycle);
114}
115
116// from interpreter
117extern void MTC0(int reg, u32 val);
118
119void pcsx_mtc0(u32 reg)
120{
121 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
122 MTC0(reg, readmem_word);
123 gen_interupt();
124}
125
126void pcsx_mtc0_ds(u32 reg)
127{
128 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
129 MTC0(reg, readmem_word);
130}
131
132void new_dyna_save(void)
133{
134 // psxRegs.intCycle is always maintained, no need to convert
135}
136
137void new_dyna_restore(void)
138{
139 int i;
140 for (i = 0; i < PSXINT_COUNT; i++)
141 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
142}
143
144void *gte_handlers[64];
145
146void *gte_handlers_nf[64] = {
147 NULL , gteRTPS_nf , NULL , NULL , NULL , NULL , gteNCLIP_nf, NULL , // 00
148 NULL , NULL , NULL , NULL , gteOP_nf , NULL , NULL , NULL , // 08
149 gteDPCS_nf, gteINTPL_nf, gteMVMVA_nf, gteNCDS_nf, gteCDP_nf, NULL , gteNCDT_nf , NULL , // 10
150 NULL , NULL , NULL , gteNCCS_nf, gteCC_nf , NULL , gteNCS_nf , NULL , // 18
151 gteNCT_nf , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
152 gteSQR_nf , gteDCPL_nf , gteDPCT_nf , NULL , NULL , gteAVSZ3_nf, gteAVSZ4_nf, NULL , // 28
153 gteRTPT_nf, NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
154 NULL , NULL , NULL , NULL , NULL , gteGPF_nf , gteGPL_nf , gteNCCT_nf, // 38
155};
156
157const char *gte_regnames[64] = {
158 NULL , "RTPS" , NULL , NULL , NULL , NULL , "NCLIP", NULL , // 00
159 NULL , NULL , NULL , NULL , "OP" , NULL , NULL , NULL , // 08
160 "DPCS", "INTPL", "MVMVA", "NCDS", "CDP", NULL , "NCDT" , NULL , // 10
161 NULL , NULL , NULL , "NCCS", "CC" , NULL , "NCS" , NULL , // 18
162 "NCT" , NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 20
163 "SQR" , "DCPL" , "DPCT" , NULL , NULL , "AVSZ3", "AVSZ4", NULL , // 28
164 "RTPT", NULL , NULL , NULL , NULL , NULL , NULL , NULL , // 30
165 NULL , NULL , NULL , NULL , NULL , "GPF" , "GPL" , "NCCT", // 38
166};
167
168/* from gte.txt.. not sure if this is any good. */
169const char gte_cycletab[64] = {
170 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
171 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
172 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
173 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
174 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
175};
176
177static int ari64_init()
178{
179 extern void (*psxCP2[64])();
180 extern void psxNULL();
181 size_t i;
182
183 new_dynarec_init();
184 new_dyna_pcsx_mem_init();
185
186 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
187 if (psxCP2[i] != psxNULL)
188 gte_handlers[i] = psxCP2[i];
189
190#if !defined(DRC_DBG) && !defined(PCNT)
191#ifdef __arm__
192 gte_handlers[0x06] = gteNCLIP_arm;
193 gte_handlers_nf[0x01] = gteRTPS_nf_arm;
194 gte_handlers_nf[0x30] = gteRTPT_nf_arm;
195#endif
196#ifdef __ARM_NEON__
197 // compiler's _nf version is still a lot slower then neon
198 // _nf_arm RTPS is roughly the same, RTPT slower
199 gte_handlers[0x01] = gte_handlers_nf[0x01] = gteRTPS_neon;
200 gte_handlers[0x30] = gte_handlers_nf[0x30] = gteRTPT_neon;
201 gte_handlers[0x12] = gte_handlers_nf[0x12] = gteMVMVA_neon;
202#endif
203#endif
204#ifdef DRC_DBG
205 memcpy(gte_handlers_nf, gte_handlers, sizeof(gte_handlers_nf));
206#endif
207 psxH_ptr = psxH;
208
209 return 0;
210}
211
212static void ari64_reset()
213{
214 printf("ari64_reset\n");
215 new_dyna_pcsx_mem_reset();
216 invalidate_all_pages();
217 new_dyna_restore();
218 pending_exception = 1;
219}
220
221// execute until predefined leave points
222// (HLE softcall exit and BIOS fastboot end)
223static void ari64_execute_until()
224{
225 schedule_timeslice();
226
227 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
228 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
229
230 new_dyna_start();
231
232 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
233 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
234}
235
236static void ari64_execute()
237{
238 while (!stop) {
239 ari64_execute_until();
240 evprintf("drc left @%08x\n", psxRegs.pc);
241 }
242}
243
244static void ari64_clear(u32 addr, u32 size)
245{
246 u32 start, end, main_ram;
247
248 size *= 4; /* PCSX uses DMA units */
249
250 evprintf("ari64_clear %08x %04x\n", addr, size);
251
252 /* check for RAM mirrors */
253 main_ram = (addr & 0xffe00000) == 0x80000000;
254
255 start = addr >> 12;
256 end = (addr + size) >> 12;
257
258 for (; start <= end; start++)
259 if (!main_ram || !invalid_code[start])
260 invalidate_block(start);
261}
262
263static void ari64_shutdown()
264{
265 new_dynarec_cleanup();
266}
267
268extern void intExecute();
269extern void intExecuteT();
270extern void intExecuteBlock();
271extern void intExecuteBlockT();
272#ifndef DRC_DBG
273#define intExecuteT intExecute
274#define intExecuteBlockT intExecuteBlock
275#endif
276
277R3000Acpu psxRec = {
278 ari64_init,
279 ari64_reset,
280#if defined(__arm__)
281 ari64_execute,
282 ari64_execute_until,
283#else
284 intExecuteT,
285 intExecuteBlockT,
286#endif
287 ari64_clear,
288 ari64_shutdown
289};
290
291// TODO: rm
292#ifndef DRC_DBG
293void do_insn_trace() {}
294void do_insn_cmp() {}
295#endif
296
297#if defined(__x86_64__) || defined(__i386__)
298unsigned int address, readmem_word, word;
299unsigned short hword;
300unsigned char byte;
301int pending_exception, stop;
302unsigned int next_interupt;
303int new_dynarec_did_compile;
304void *psxH_ptr;
305void new_dynarec_init() {}
306void new_dyna_start() {}
307void new_dynarec_cleanup() {}
308void new_dynarec_clear_full() {}
309void invalidate_all_pages() {}
310void invalidate_block(unsigned int block) {}
311void new_dyna_pcsx_mem_init(void) {}
312void new_dyna_pcsx_mem_reset(void) {}
313#endif
314
315#ifdef DRC_DBG
316
317#include <stddef.h>
318static FILE *f;
319extern u32 last_io_addr;
320
321static void dump_mem(const char *fname, void *mem, size_t size)
322{
323 FILE *f1 = fopen(fname, "wb");
324 if (f1 == NULL)
325 f1 = fopen(strrchr(fname, '/') + 1, "wb");
326 fwrite(mem, 1, size, f1);
327 fclose(f1);
328}
329
330static u32 memcheck_read(u32 a)
331{
332 if ((a >> 16) == 0x1f80)
333 // scratchpad/IO
334 return *(u32 *)(psxH + (a & 0xfffc));
335
336 if ((a >> 16) == 0x1f00)
337 // parallel
338 return *(u32 *)(psxP + (a & 0xfffc));
339
340// if ((a & ~0xe0600000) < 0x200000)
341 // RAM
342 return *(u32 *)(psxM + (a & 0x1ffffc));
343}
344
345void do_insn_trace(void)
346{
347 static psxRegisters oldregs;
348 static u32 old_io_addr = (u32)-1;
349 static u32 old_io_data = 0xbad0c0de;
350 u32 *allregs_p = (void *)&psxRegs;
351 u32 *allregs_o = (void *)&oldregs;
352 u32 io_data;
353 int i;
354 u8 byte;
355
356//last_io_addr = 0x5e2c8;
357 if (f == NULL)
358 f = fopen("tracelog", "wb");
359
360 oldregs.code = psxRegs.code; // don't care
361 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
362 if (allregs_p[i] != allregs_o[i]) {
363 fwrite(&i, 1, 1, f);
364 fwrite(&allregs_p[i], 1, 4, f);
365 allregs_o[i] = allregs_p[i];
366 }
367 }
368 if (old_io_addr != last_io_addr) {
369 byte = 0xfd;
370 fwrite(&byte, 1, 1, f);
371 fwrite(&last_io_addr, 1, 4, f);
372 old_io_addr = last_io_addr;
373 }
374 io_data = memcheck_read(last_io_addr);
375 if (old_io_data != io_data) {
376 byte = 0xfe;
377 fwrite(&byte, 1, 1, f);
378 fwrite(&io_data, 1, 4, f);
379 old_io_data = io_data;
380 }
381 byte = 0xff;
382 fwrite(&byte, 1, 1, f);
383
384#if 0
385 if (psxRegs.cycle == 190230) {
386 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
387 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
388 printf("dumped\n");
389 exit(1);
390 }
391#endif
392}
393
394static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
395 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
396 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
397 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
398 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
399 "lo", "hi",
400 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
401 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
402 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
403 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
404
405 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
406 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
407 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
408 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
409
410 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
411 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
412 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
413 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
414
415 "PC", "code", "cycle", "interrupt",
416};
417
418static struct {
419 int reg;
420 u32 val, val_expect;
421 u32 pc, cycle;
422} miss_log[64];
423static int miss_log_i;
424#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
425#define miss_log_mask (miss_log_len-1)
426
427static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
428{
429 miss_log[miss_log_i].reg = reg;
430 miss_log[miss_log_i].val = val;
431 miss_log[miss_log_i].val_expect = val_expect;
432 miss_log[miss_log_i].pc = pc;
433 miss_log[miss_log_i].cycle = cycle;
434 miss_log_i = (miss_log_i + 1) & miss_log_mask;
435}
436
437void breakme() {}
438
439void do_insn_cmp(void)
440{
441 static psxRegisters rregs;
442 static u32 mem_addr, mem_val;
443 u32 *allregs_p = (void *)&psxRegs;
444 u32 *allregs_e = (void *)&rregs;
445 static u32 ppc, failcount;
446 int i, ret, bad = 0;
447 u8 code;
448
449 if (f == NULL)
450 f = fopen("tracelog", "rb");
451
452 while (1) {
453 if ((ret = fread(&code, 1, 1, f)) <= 0)
454 break;
455 if (ret <= 0)
456 break;
457 if (code == 0xff)
458 break;
459 if (code == 0xfd) {
460 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
461 break;
462 continue;
463 }
464 if (code == 0xfe) {
465 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
466 break;
467 continue;
468 }
469 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
470 break;
471 }
472
473 if (ret <= 0) {
474 printf("EOF?\n");
475 goto end;
476 }
477
478 psxRegs.code = rregs.code; // don't care
479 psxRegs.cycle = rregs.cycle;
480 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
481
482//if (psxRegs.cycle == 166172) breakme();
483
484 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
485 mem_val == memcheck_read(mem_addr)
486 ) {
487 failcount = 0;
488 goto ok;
489 }
490
491 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
492 if (allregs_p[i] != allregs_e[i]) {
493 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
494 bad++;
495 }
496 }
497
498 if (mem_val != memcheck_read(mem_addr)) {
499 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
500 goto end;
501 }
502
503 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
504 static int last_mcycle;
505 if (last_mcycle != psxRegs.cycle >> 20) {
506 printf("%u\n", psxRegs.cycle);
507 last_mcycle = psxRegs.cycle >> 20;
508 }
509 failcount++;
510 goto ok;
511 }
512
513end:
514 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
515 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
516 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
517 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
518 printf("-- %d\n", bad);
519 for (i = 0; i < 8; i++)
520 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
521 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
522 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
523 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
524 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
525 exit(1);
526ok:
527 psxRegs.cycle = rregs.cycle + 2; // sync timing
528 ppc = psxRegs.pc;
529}
530
531#endif