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