support armv5 build
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7e605697 1/*
009faf24 2 * (C) GraÅžvydas "notaz" Ignotas, 2010-2011
7e605697 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"
009faf24 17#include "../gte_neon.h"
7139f3c8 18
ae602c19 19#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
20
7139f3c8 21//#define evprintf printf
22#define evprintf(...)
23
f95a77f7 24char invalid_code[0x100000];
d28b54b1 25u32 event_cycles[PSXINT_COUNT];
f95a77f7 26
654e8cfb 27static void schedule_timeslice(void)
f95a77f7 28{
654e8cfb 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}
ae602c19 53
52082bc1 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,
528ad661 63 [PSXINT_MDECINDMA] = mdec0Interrupt,
57a757ce 64 [PSXINT_GPUOTCDMA] = gpuotcInterrupt,
9f8b032d 65 [PSXINT_CDRDMA] = cdrDmaInterrupt,
66 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
7f457614 67 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
52082bc1 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
654e8cfb 99void gen_interupt()
100{
654e8cfb 101 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 102
52082bc1 103 irq_test();
104 //psxBranchTest();
105 //pending_exception = 1;
7139f3c8 106
654e8cfb 107 schedule_timeslice();
ae602c19 108
654e8cfb 109 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
110 next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 111}
112
fca1aef2 113// from interpreter
114extern void MTC0(int reg, u32 val);
115
116void pcsx_mtc0(u32 reg)
28bc5688 117{
fca1aef2 118 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
119 MTC0(reg, readmem_word);
120 gen_interupt();
121}
28bc5688 122
fca1aef2 123void pcsx_mtc0_ds(u32 reg)
124{
125 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
126 MTC0(reg, readmem_word);
28bc5688 127}
128
52082bc1 129void new_dyna_save(void)
130{
131 // psxRegs.intCycle is always maintained, no need to convert
132}
133
134void new_dyna_restore(void)
135{
136 int i;
9f8b032d 137 for (i = 0; i < PSXINT_COUNT; i++)
52082bc1 138 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
139}
140
b9b61529 141void *gte_handlers[64];
142
143/* from gte.txt.. not sure if this is any good. */
144const char gte_cycletab[64] = {
145 /* 1 2 3 4 5 6 7 8 9 a b c d e f */
146 0, 15, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 6, 0, 0, 0,
147 8, 8, 8, 19, 13, 0, 44, 0, 0, 0, 0, 17, 11, 0, 14, 0,
148 30, 0, 0, 0, 0, 0, 0, 0, 5, 8, 17, 0, 0, 5, 6, 0,
149 23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 39,
150};
f95a77f7 151
152static int ari64_init()
153{
b9b61529 154 extern void (*psxCP2[64])();
155 extern void psxNULL();
f95a77f7 156 size_t i;
b9b61529 157
f95a77f7 158 new_dynarec_init();
7e605697 159 new_dyna_pcsx_mem_init();
7139f3c8 160
ae602c19 161 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 162 if (psxCP2[i] != psxNULL)
163 gte_handlers[i] = psxCP2[i];
a80ae4a0 164#ifndef DRC_DBG
165#ifdef __ARM_NEON__
009faf24 166 gte_handlers[0x01] = gteRTPS_neon;
167 gte_handlers[0x30] = gteRTPT_neon;
168 gte_handlers[0x12] = gteMVMVA_neon;
169 gte_handlers[0x06] = gteNCLIP_neon;
a80ae4a0 170#endif
009faf24 171#endif
7e605697 172 psxH_ptr = psxH;
173
b9b61529 174 return 0;
f95a77f7 175}
176
177static void ari64_reset()
178{
f95a77f7 179 printf("ari64_reset\n");
7e605697 180 new_dyna_pcsx_mem_reset();
4b421010 181 invalidate_all_pages();
7f457614 182 new_dyna_restore();
4b421010 183 pending_exception = 1;
f95a77f7 184}
185
e4eb18c1 186// execute until predefined leave points
187// (HLE softcall exit and BIOS fastboot end)
188static void ari64_execute_until()
f95a77f7 189{
654e8cfb 190 schedule_timeslice();
191
192 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
193 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 194
b9b61529 195 new_dyna_start();
654e8cfb 196
197 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
198 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 199}
200
e4eb18c1 201static void ari64_execute()
202{
203 while (!stop) {
204 ari64_execute_until();
205 evprintf("drc left @%08x\n", psxRegs.pc);
206 }
207}
208
4b421010 209static void ari64_clear(u32 addr, u32 size)
f95a77f7 210{
0ce47d46 211 u32 start, end, main_ram;
4b421010 212
76739a08 213 size *= 4; /* PCSX uses DMA units */
214
4b421010 215 evprintf("ari64_clear %08x %04x\n", addr, size);
216
217 /* check for RAM mirrors */
0ce47d46 218 main_ram = (addr & 0xffe00000) == 0x80000000;
4b421010 219
220 start = addr >> 12;
221 end = (addr + size) >> 12;
222
223 for (; start <= end; start++)
0ce47d46 224 if (!main_ram || !invalid_code[start])
4b421010 225 invalidate_block(start);
f95a77f7 226}
227
228static void ari64_shutdown()
229{
230 new_dynarec_cleanup();
231}
232
7139f3c8 233extern void intExecute();
234extern void intExecuteT();
235extern void intExecuteBlock();
236extern void intExecuteBlockT();
237#ifndef DRC_DBG
238#define intExecuteT intExecute
239#define intExecuteBlockT intExecuteBlock
240#endif
241
f95a77f7 242R3000Acpu psxRec = {
243 ari64_init,
244 ari64_reset,
2185e39b 245#if defined(__arm__)
f95a77f7 246 ari64_execute,
e4eb18c1 247 ari64_execute_until,
7139f3c8 248#else
249 intExecuteT,
250 intExecuteBlockT,
251#endif
f95a77f7 252 ari64_clear,
253 ari64_shutdown
254};
7139f3c8 255
256// TODO: rm
257#ifndef DRC_DBG
258void do_insn_trace() {}
259void do_insn_cmp() {}
260#endif
261
262#if defined(__x86_64__) || defined(__i386__)
263unsigned int address, readmem_word, word;
264unsigned short hword;
265unsigned char byte;
ccf51908 266int pending_exception, stop;
7139f3c8 267unsigned int next_interupt;
7e605697 268void *psxH_ptr;
7139f3c8 269void new_dynarec_init() {}
3eb78778 270void new_dyna_start() {}
7139f3c8 271void new_dynarec_cleanup() {}
2c886904 272void new_dynarec_clear_full() {}
ccf51908 273void invalidate_all_pages() {}
274void invalidate_block(unsigned int block) {}
7e605697 275void new_dyna_pcsx_mem_init(void) {}
276void new_dyna_pcsx_mem_reset(void) {}
7139f3c8 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");
3eb78778 288 if (f1 == NULL)
289 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 290 fwrite(mem, 1, size, f1);
291 fclose(f1);
292}
293
2185e39b 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
7139f3c8 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;
2185e39b 316 u32 io_data;
7139f3c8 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 }
2185e39b 338 io_data = memcheck_read(last_io_addr);
339 if (old_io_data != io_data) {
7139f3c8 340 byte = 0xfe;
341 fwrite(&byte, 1, 1, f);
2185e39b 342 fwrite(&io_data, 1, 4, f);
343 old_io_data = io_data;
7139f3c8 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
3eb78778 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
7139f3c8 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
2185e39b 443 psxRegs.cycle = rregs.cycle;
444 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
7139f3c8 445
446//if (psxRegs.cycle == 166172) breakme();
7139f3c8 447
448 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
2185e39b 449 mem_val == memcheck_read(mem_addr)
7139f3c8 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]) {
3eb78778 457 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 458 bad++;
459 }
460 }
461
2185e39b 462 if (mem_val != memcheck_read(mem_addr)) {
463 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
7139f3c8 464 goto end;
465 }
466
467 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
3eb78778 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 }
7139f3c8 473 failcount++;
474 goto ok;
475 }
476
477end:
3eb78778 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],
87c06e51 485 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
7139f3c8 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