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