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