drc: handle invalidate on clear() calls and reset
[pcsx_rearmed.git] / libpcsxcore / new_dynarec / emu_if.c
CommitLineData
7139f3c8 1// pending_exception?
822b27d1 2// swi 0 in do_unalignedwritestub?
f95a77f7 3#include <stdio.h>
4
5#include "emu_if.h"
7139f3c8 6#include "../psxmem.h"
7#include "../psxhle.h"
8
ae602c19 9#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
10
7139f3c8 11//#define memprintf printf
12#define memprintf(...)
13//#define evprintf printf
14#define evprintf(...)
15
f95a77f7 16char invalid_code[0x100000];
ae602c19 17u32 event_cycles[6];
f95a77f7 18
7139f3c8 19void MTC0_()
f95a77f7 20{
7139f3c8 21 extern void psxMTC0();
22
b9b61529 23 memprintf("ari64 MTC0 %08x\n", psxRegs.code);
7139f3c8 24 psxMTC0();
25 pending_exception = 1; /* FIXME? */
f95a77f7 26}
27
654e8cfb 28static void schedule_timeslice(void)
f95a77f7 29{
654e8cfb 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}
ae602c19 54
654e8cfb 55void gen_interupt()
56{
57 //evprintf("ari64_gen_interupt\n");
58 evprintf(" +ge %08x, %u->%u\n", psxRegs.pc, psxRegs.cycle, next_interupt);
7139f3c8 59#ifdef DRC_DBG
60 psxRegs.cycle += 2;
7139f3c8 61#endif
62
63 psxBranchTest();
64
654e8cfb 65 schedule_timeslice();
ae602c19 66
654e8cfb 67 evprintf(" -ge %08x, %u->%u (%d)\n", psxRegs.pc, psxRegs.cycle,
68 next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 69
70 pending_exception = 1; /* FIXME */
f95a77f7 71}
72
73void check_interupt()
74{
7139f3c8 75 printf("ari64_check_interupt\n");
f95a77f7 76}
77
78void read_nomem_new()
79{
7139f3c8 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);
f95a77f7 105}
106
7139f3c8 107static void write_mem16()
f95a77f7 108{
7139f3c8 109 memprintf("ari64_write_mem16 %08x, %04x, PC~=%08x\n", address, hword, psxRegs.pc);
110 psxMemWrite16(address, hword);
f95a77f7 111}
112
7139f3c8 113static void write_mem32()
f95a77f7 114{
7139f3c8 115 memprintf("ari64_write_mem32 %08x, %08x, PC~=%08x\n", address, word, psxRegs.pc);
116 psxMemWrite32(address, word);
f95a77f7 117}
118
119void (*readmem[0x10000])();
120void (*readmemb[0x10000])();
121void (*readmemh[0x10000])();
122void (*writemem[0x10000])();
123void (*writememb[0x10000])();
124void (*writememh[0x10000])();
125
b9b61529 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};
f95a77f7 136
137static int ari64_init()
138{
b9b61529 139 extern void (*psxCP2[64])();
140 extern void psxNULL();
f95a77f7 141 size_t i;
b9b61529 142
f95a77f7 143 new_dynarec_init();
144
ae602c19 145 for (i = 0; i < ARRAY_SIZE(readmem); i++) {
7139f3c8 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;
f95a77f7 152 }
7139f3c8 153
ae602c19 154 for (i = 0; i < ARRAY_SIZE(gte_handlers); i++)
b9b61529 155 if (psxCP2[i] != psxNULL)
156 gte_handlers[i] = psxCP2[i];
157
b9b61529 158 return 0;
f95a77f7 159}
160
161static void ari64_reset()
162{
f95a77f7 163 printf("ari64_reset\n");
4b421010 164 invalidate_all_pages();
165 pending_exception = 1;
f95a77f7 166}
167
168static void ari64_execute()
169{
654e8cfb 170 schedule_timeslice();
171
172 evprintf("ari64_execute %08x, %u->%u (%d)\n", psxRegs.pc,
173 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
7139f3c8 174
b9b61529 175 new_dyna_start();
654e8cfb 176
177 evprintf("ari64_execute end %08x, %u->%u (%d)\n", psxRegs.pc,
178 psxRegs.cycle, next_interupt, next_interupt - psxRegs.cycle);
f95a77f7 179}
180
4b421010 181static void ari64_clear(u32 addr, u32 size)
f95a77f7 182{
4b421010 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);
f95a77f7 199}
200
201static void ari64_shutdown()
202{
203 new_dynarec_cleanup();
204}
205
7139f3c8 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
f95a77f7 215R3000Acpu psxRec = {
216 ari64_init,
217 ari64_reset,
7139f3c8 218#if 1
f95a77f7 219 ari64_execute,
7139f3c8 220 ari64_execute,
221#else
222 intExecuteT,
223 intExecuteBlockT,
224#endif
f95a77f7 225 ari64_clear,
226 ari64_shutdown
227};
7139f3c8 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;
7139f3c8 241void new_dynarec_init() {}
3eb78778 242void new_dyna_start() {}
7139f3c8 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");
3eb78778 255 if (f1 == NULL)
256 f1 = fopen(strrchr(fname, '/') + 1, "wb");
7139f3c8 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
3eb78778 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
7139f3c8 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]) {
3eb78778 412 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
7139f3c8 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) {
3eb78778 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 }
7139f3c8 428 failcount++;
429 goto ok;
430 }
431
432end:
3eb78778 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]);
7139f3c8 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