drc: fix BxxZAL
[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,
2185e39b 227#if defined(__arm__)
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
2185e39b 275static u32 memcheck_read(u32 a)
276{
277 if ((a >> 16) == 0x1f80)
278 // scratchpad/IO
279 return *(u32 *)(psxH + (a & 0xfffc));
280
281 if ((a >> 16) == 0x1f00)
282 // parallel
283 return *(u32 *)(psxP + (a & 0xfffc));
284
285// if ((a & ~0xe0600000) < 0x200000)
286 // RAM
287 return *(u32 *)(psxM + (a & 0x1ffffc));
288}
289
7139f3c8 290void do_insn_trace(void)
291{
292 static psxRegisters oldregs;
293 static u32 old_io_addr = (u32)-1;
294 static u32 old_io_data = 0xbad0c0de;
295 u32 *allregs_p = (void *)&psxRegs;
296 u32 *allregs_o = (void *)&oldregs;
2185e39b 297 u32 io_data;
7139f3c8 298 int i;
299 u8 byte;
300
301//last_io_addr = 0x5e2c8;
302 if (f == NULL)
303 f = fopen("tracelog", "wb");
304
305 oldregs.code = psxRegs.code; // don't care
306 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
307 if (allregs_p[i] != allregs_o[i]) {
308 fwrite(&i, 1, 1, f);
309 fwrite(&allregs_p[i], 1, 4, f);
310 allregs_o[i] = allregs_p[i];
311 }
312 }
313 if (old_io_addr != last_io_addr) {
314 byte = 0xfd;
315 fwrite(&byte, 1, 1, f);
316 fwrite(&last_io_addr, 1, 4, f);
317 old_io_addr = last_io_addr;
318 }
2185e39b 319 io_data = memcheck_read(last_io_addr);
320 if (old_io_data != io_data) {
7139f3c8 321 byte = 0xfe;
322 fwrite(&byte, 1, 1, f);
2185e39b 323 fwrite(&io_data, 1, 4, f);
324 old_io_data = io_data;
7139f3c8 325 }
326 byte = 0xff;
327 fwrite(&byte, 1, 1, f);
328
329#if 0
330 if (psxRegs.cycle == 190230) {
331 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
332 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
333 printf("dumped\n");
334 exit(1);
335 }
336#endif
337}
338
339static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
340 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
341 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
342 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
343 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
344 "lo", "hi",
345 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
346 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
347 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
348 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
349
350 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
351 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
352 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
353 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
354
355 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
356 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
357 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
358 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
359
360 "PC", "code", "cycle", "interrupt",
361};
362
3eb78778 363static struct {
364 int reg;
365 u32 val, val_expect;
366 u32 pc, cycle;
367} miss_log[64];
368static int miss_log_i;
369#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
370#define miss_log_mask (miss_log_len-1)
371
372static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
373{
374 miss_log[miss_log_i].reg = reg;
375 miss_log[miss_log_i].val = val;
376 miss_log[miss_log_i].val_expect = val_expect;
377 miss_log[miss_log_i].pc = pc;
378 miss_log[miss_log_i].cycle = cycle;
379 miss_log_i = (miss_log_i + 1) & miss_log_mask;
380}
381
7139f3c8 382void breakme() {}
383
384void do_insn_cmp(void)
385{
386 static psxRegisters rregs;
387 static u32 mem_addr, mem_val;
388 u32 *allregs_p = (void *)&psxRegs;
389 u32 *allregs_e = (void *)&rregs;
390 static u32 ppc, failcount;
391 int i, ret, bad = 0;
392 u8 code;
393
394 if (f == NULL)
395 f = fopen("tracelog", "rb");
396
397 while (1) {
398 if ((ret = fread(&code, 1, 1, f)) <= 0)
399 break;
400 if (ret <= 0)
401 break;
402 if (code == 0xff)
403 break;
404 if (code == 0xfd) {
405 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
406 break;
407 continue;
408 }
409 if (code == 0xfe) {
410 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
411 break;
412 continue;
413 }
414 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
415 break;
416 }
417
418 if (ret <= 0) {
419 printf("EOF?\n");
420 goto end;
421 }
422
423 psxRegs.code = rregs.code; // don't care
2185e39b 424 psxRegs.cycle = rregs.cycle;
425 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 426
427//if (psxRegs.cycle == 166172) breakme();
7139f3c8 428
429 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 430 mem_val == memcheck_read(mem_addr)
7139f3c8 431 ) {
432 failcount = 0;
433 goto ok;
434 }
435
436 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
437 if (allregs_p[i] != allregs_e[i]) {
3eb78778 438 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 439 bad++;
440 }
441 }
442
2185e39b 443 if (mem_val != memcheck_read(mem_addr)) {
444 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 445 goto end;
446 }
447
448 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 449 static int last_mcycle;
450 if (last_mcycle != psxRegs.cycle >> 20) {
451 printf("%u\n", psxRegs.cycle);
452 last_mcycle = psxRegs.cycle >> 20;
453 }
7139f3c8 454 failcount++;
455 goto ok;
456 }
457
458end:
3eb78778 459 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
460 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
461 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
462 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
463 printf("-- %d\n", bad);
464 for (i = 0; i < 8; i++)
465 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
87c06e51 466 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 467 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
468 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
469 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
470 exit(1);
471ok:
472 psxRegs.cycle = rregs.cycle + 2; // sync timing
473 ppc = psxRegs.pc;
474}
475
476#endif