drc: rm x86 stuff - it's unmaintained here
[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 [PSXINT_CDRDMA] = cdrDmaInterrupt,
65 [PSXINT_CDRLID] = cdrLidSeekInterrupt,
66 [PSXINT_CDRPLAY] = cdrPlayInterrupt,
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
98void gen_interupt()
99{
100 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
101#ifdef DRC_DBG
102 psxRegs.cycle += 2;
103#endif
104
105 irq_test();
106 //psxBranchTest();
107 //pending_exception = 1;
108
109 schedule_timeslice();
110
111 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
112 next_interupt, next_interupt - psxRegs.cycle);
113}
114
115// from interpreter
116extern void MTC0(int reg, u32 val);
117
118void pcsx_mtc0(u32 reg)
119{
120 evprintf("MTC0 %d #%x @%08x %u\n", reg, readmem_word, psxRegs.pc, psxRegs.cycle);
121 MTC0(reg, readmem_word);
122 gen_interupt();
123}
124
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);
129}
130
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;
139 for (i = 0; i < PSXINT_COUNT; i++)
140 event_cycles[i] = psxRegs.intCycle[i].sCycle + psxRegs.intCycle[i].cycle;
141}
142
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};
153
154static int ari64_init()
155{
156 extern void (*psxCP2[64])();
157 extern void psxNULL();
158 extern void *psxH_ptr;
159 size_t i;
160
161 new_dynarec_init();
162 new_dyna_pcsx_mem_init();
163
164 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
165 if (psxCP2[i] != psxNULL)
166 gte_handlers[i] = psxCP2[i];
167
168 psxH_ptr = psxH;
169
170 return 0;
171}
172
173static void ari64_reset()
174{
175 printf("ari64_reset\n");
176 new_dyna_pcsx_mem_reset();
177 invalidate_all_pages();
178 new_dyna_restore();
179 pending_exception = 1;
180}
181
182// execute until predefined leave points
183// (HLE softcall exit and BIOS fastboot end)
184static void ari64_execute_until()
185{
186 schedule_timeslice();
187
188 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
189 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
190
191 new_dyna_start();
192
193 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
194 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
195}
196
197static void ari64_execute()
198{
199 while (!stop) {
200 ari64_execute_until();
201 evprintf("drc left @%08x\n", psxRegs.pc);
202 }
203}
204
205static void ari64_clear(u32 addr, u32 size)
206{
207 u32 start, end, main_ram;
208
209 size *= 4; /* PCSX uses DMA units */
210
211 evprintf("ari64_clear %08x %04x\n", addr, size);
212
213 /* check for RAM mirrors */
214 main_ram = (addr & 0xffe00000) == 0x80000000;
215
216 start = addr >> 12;
217 end = (addr + size) >> 12;
218
219 for (; start <= end; start++)
220 if (!main_ram || !invalid_code[start])
221 invalidate_block(start);
222}
223
224static void ari64_shutdown()
225{
226 new_dynarec_cleanup();
227}
228
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
238R3000Acpu psxRec = {
239 ari64_init,
240 ari64_reset,
241#if defined(__arm__)
242 ari64_execute,
243 ari64_execute_until,
244#else
245 intExecuteT,
246 intExecuteBlockT,
247#endif
248 ari64_clear,
249 ari64_shutdown
250};
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;
262int pending_exception, stop;
263unsigned int next_interupt;
264void *psxH_ptr;
265void new_dynarec_init() {}
266void new_dyna_start() {}
267void new_dynarec_cleanup() {}
268void invalidate_all_pages() {}
269void invalidate_block(unsigned int block) {}
270void new_dyna_pcsx_mem_init(void) {}
271void new_dyna_pcsx_mem_reset(void) {}
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");
283 if (f1 == NULL)
284 f1 = fopen(strrchr(fname, '/') + 1, "wb");
285 fwrite(mem, 1, size, f1);
286 fclose(f1);
287}
288
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
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;
311 u32 io_data;
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 }
333 io_data = memcheck_read(last_io_addr);
334 if (old_io_data != io_data) {
335 byte = 0xfe;
336 fwrite(&byte, 1, 1, f);
337 fwrite(&io_data, 1, 4, f);
338 old_io_data = io_data;
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
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
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
438 psxRegs.cycle = rregs.cycle;
439 psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
440
441//if (psxRegs.cycle == 166172) breakme();
442
443 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
444 mem_val == memcheck_read(mem_addr)
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]) {
452 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
453 bad++;
454 }
455 }
456
457 if (mem_val != memcheck_read(mem_addr)) {
458 printf("bad mem @%08x: %08x %08x\n", mem_addr, memcheck_read(mem_addr), mem_val);
459 goto end;
460 }
461
462 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
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 }
468 failcount++;
469 goto ok;
470 }
471
472end:
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],
480 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+24]);
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