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