io asm: always write out to psxH, like C code does
[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};
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
95void gen_interupt()
96{
97 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
98#ifdef DRC_DBG
99 psxRegs.cycle += 2;
100#endif
101
102 irq_test();
103 //psxBranchTest();
104 //pending_exception = 1;
105
106 schedule_timeslice();
107
108 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
109 next_interupt, next_interupt - psxRegs.cycle);
110}
111
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
121void check_interupt()
122{
123 /* FIXME (also asm) */
124 printf("ari64_check_interupt\n");
125}
126
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
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};
149
150static int ari64_init()
151{
152 extern void (*psxCP2[64])();
153 extern void psxNULL();
154 extern void *psxH_ptr;
155 size_t i;
156
157 new_dynarec_init();
158 new_dyna_pcsx_mem_init();
159
160 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
161 if (psxCP2[i] != psxNULL)
162 gte_handlers[i] = psxCP2[i];
163
164 psxH_ptr = psxH;
165
166 return 0;
167}
168
169static void ari64_reset()
170{
171 printf("ari64_reset\n");
172 new_dyna_pcsx_mem_reset();
173 invalidate_all_pages();
174 pending_exception = 1;
175}
176
177static void ari64_execute()
178{
179 schedule_timeslice();
180
181 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
182 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
183
184 new_dyna_start();
185
186 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
187 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
188}
189
190static void ari64_clear(u32 addr, u32 size)
191{
192 u32 start, end;
193
194 evprintf("ari64_clear %08x %04x\n", addr, size);
195
196 /* check for RAM mirrors */
197 if ((addr & ~0xe0600000) < 0x200000) {
198 addr &= ~0xe0600000;
199 addr |= 0x80000000;
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);
208}
209
210static void ari64_shutdown()
211{
212 new_dynarec_cleanup();
213}
214
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
224R3000Acpu psxRec = {
225 ari64_init,
226 ari64_reset,
227#if 1
228 ari64_execute,
229 ari64_execute,
230#else
231 intExecuteT,
232 intExecuteBlockT,
233#endif
234 ari64_clear,
235 ari64_shutdown
236};
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;
248int pending_exception, stop;
249unsigned int next_interupt;
250void *psxH_ptr;
251void new_dynarec_init() {}
252void new_dyna_start() {}
253void new_dynarec_cleanup() {}
254void invalidate_all_pages() {}
255void invalidate_block(unsigned int block) {}
256void new_dyna_pcsx_mem_init(void) {}
257void new_dyna_pcsx_mem_reset(void) {}
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");
269 if (f1 == NULL)
270 f1 = fopen(strrchr(fname, '/') + 1, "wb");
271 fwrite(mem, 1, size, f1);
272 fclose(f1);
273}
274
275void do_insn_trace(void)
276{
277 static psxRegisters oldregs;
278 static u32 old_io_addr = (u32)-1;
279 static u32 old_io_data = 0xbad0c0de;
280 u32 *allregs_p = (void *)&psxRegs;
281 u32 *allregs_o = (void *)&oldregs;
282 u32 *io_data;
283 int i;
284 u8 byte;
285
286//last_io_addr = 0x5e2c8;
287 if (f == NULL)
288 f = fopen("tracelog", "wb");
289
290 oldregs.code = psxRegs.code; // don't care
291 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
292 if (allregs_p[i] != allregs_o[i]) {
293 fwrite(&i, 1, 1, f);
294 fwrite(&allregs_p[i], 1, 4, f);
295 allregs_o[i] = allregs_p[i];
296 }
297 }
298 if (old_io_addr != last_io_addr) {
299 byte = 0xfd;
300 fwrite(&byte, 1, 1, f);
301 fwrite(&last_io_addr, 1, 4, f);
302 old_io_addr = last_io_addr;
303 }
304 io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
305 if (old_io_data != *io_data) {
306 byte = 0xfe;
307 fwrite(&byte, 1, 1, f);
308 fwrite(io_data, 1, 4, f);
309 old_io_data = *io_data;
310 }
311 byte = 0xff;
312 fwrite(&byte, 1, 1, f);
313
314#if 0
315 if (psxRegs.cycle == 190230) {
316 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
317 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
318 printf("dumped\n");
319 exit(1);
320 }
321#endif
322}
323
324static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
325 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
326 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
327 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
328 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
329 "lo", "hi",
330 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
331 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
332 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
333 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
334
335 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
336 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
337 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
338 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
339
340 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
341 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
342 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
343 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
344
345 "PC", "code", "cycle", "interrupt",
346};
347
348static struct {
349 int reg;
350 u32 val, val_expect;
351 u32 pc, cycle;
352} miss_log[64];
353static int miss_log_i;
354#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
355#define miss_log_mask (miss_log_len-1)
356
357static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
358{
359 miss_log[miss_log_i].reg = reg;
360 miss_log[miss_log_i].val = val;
361 miss_log[miss_log_i].val_expect = val_expect;
362 miss_log[miss_log_i].pc = pc;
363 miss_log[miss_log_i].cycle = cycle;
364 miss_log_i = (miss_log_i + 1) & miss_log_mask;
365}
366
367void breakme() {}
368
369void do_insn_cmp(void)
370{
371 static psxRegisters rregs;
372 static u32 mem_addr, mem_val;
373 u32 *allregs_p = (void *)&psxRegs;
374 u32 *allregs_e = (void *)&rregs;
375 static u32 ppc, failcount;
376 int i, ret, bad = 0;
377 u8 code;
378
379 if (f == NULL)
380 f = fopen("tracelog", "rb");
381
382 while (1) {
383 if ((ret = fread(&code, 1, 1, f)) <= 0)
384 break;
385 if (ret <= 0)
386 break;
387 if (code == 0xff)
388 break;
389 if (code == 0xfd) {
390 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
391 break;
392 continue;
393 }
394 if (code == 0xfe) {
395 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
396 break;
397 continue;
398 }
399 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
400 break;
401 }
402
403 if (ret <= 0) {
404 printf("EOF?\n");
405 goto end;
406 }
407
408 psxRegs.code = rregs.code; // don't care
409psxRegs.cycle = rregs.cycle;
410psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
411
412//if (psxRegs.cycle == 166172) breakme();
413//if (psxRegs.cycle > 11296376) printf("pc=%08x %u %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
414
415 mem_addr &= 0x1ffffc;
416
417 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
418 mem_val == *(u32 *)(psxM + mem_addr)
419 ) {
420 failcount = 0;
421 goto ok;
422 }
423
424 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
425 if (allregs_p[i] != allregs_e[i]) {
426 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
427 bad++;
428 }
429 }
430
431 if (mem_val != *(u32 *)(psxM + mem_addr)) {
432 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
433 goto end;
434 }
435
436 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
437 static int last_mcycle;
438 if (last_mcycle != psxRegs.cycle >> 20) {
439 printf("%u\n", psxRegs.cycle);
440 last_mcycle = psxRegs.cycle >> 20;
441 }
442 failcount++;
443 goto ok;
444 }
445
446end:
447 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
448 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
449 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
450 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
451 printf("-- %d\n", bad);
452 for (i = 0; i < 8; i++)
453 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
454 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
455 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
456 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
457 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
458 exit(1);
459ok:
460 psxRegs.cycle = rregs.cycle + 2; // sync timing
461 ppc = psxRegs.pc;
462}
463
464#endif