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