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