fix x86 build, minor refactoring
[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, stop;
240unsigned int next_interupt;
241void new_dynarec_init() {}
242void new_dyna_start() {}
243void new_dynarec_cleanup() {}
244void invalidate_all_pages() {}
245void invalidate_block(unsigned int block) {}
246#endif
247
248#ifdef DRC_DBG
249
250#include <stddef.h>
251static FILE *f;
252extern u32 last_io_addr;
253
254static void dump_mem(const char *fname, void *mem, size_t size)
255{
256 FILE *f1 = fopen(fname, "wb");
257 if (f1 == NULL)
258 f1 = fopen(strrchr(fname, '/') + 1, "wb");
259 fwrite(mem, 1, size, f1);
260 fclose(f1);
261}
262
263void do_insn_trace(void)
264{
265 static psxRegisters oldregs;
266 static u32 old_io_addr = (u32)-1;
267 static u32 old_io_data = 0xbad0c0de;
268 u32 *allregs_p = (void *)&psxRegs;
269 u32 *allregs_o = (void *)&oldregs;
270 u32 *io_data;
271 int i;
272 u8 byte;
273
274//last_io_addr = 0x5e2c8;
275 if (f == NULL)
276 f = fopen("tracelog", "wb");
277
278 oldregs.code = psxRegs.code; // don't care
279 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
280 if (allregs_p[i] != allregs_o[i]) {
281 fwrite(&i, 1, 1, f);
282 fwrite(&allregs_p[i], 1, 4, f);
283 allregs_o[i] = allregs_p[i];
284 }
285 }
286 if (old_io_addr != last_io_addr) {
287 byte = 0xfd;
288 fwrite(&byte, 1, 1, f);
289 fwrite(&last_io_addr, 1, 4, f);
290 old_io_addr = last_io_addr;
291 }
292 io_data = (void *)(psxM + (last_io_addr&0x1ffffc));
293 if (old_io_data != *io_data) {
294 byte = 0xfe;
295 fwrite(&byte, 1, 1, f);
296 fwrite(io_data, 1, 4, f);
297 old_io_data = *io_data;
298 }
299 byte = 0xff;
300 fwrite(&byte, 1, 1, f);
301
302#if 0
303 if (psxRegs.cycle == 190230) {
304 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram_i.dump", psxM, 0x200000);
305 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs_i.dump", psxH, 0x10000);
306 printf("dumped\n");
307 exit(1);
308 }
309#endif
310}
311
312static const char *regnames[offsetof(psxRegisters, intCycle) / 4] = {
313 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
314 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
315 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
316 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
317 "lo", "hi",
318 "C0_0", "C0_1", "C0_2", "C0_3", "C0_4", "C0_5", "C0_6", "C0_7",
319 "C0_8", "C0_9", "C0_10", "C0_11", "C0_12", "C0_13", "C0_14", "C0_15",
320 "C0_16", "C0_17", "C0_18", "C0_19", "C0_20", "C0_21", "C0_22", "C0_23",
321 "C0_24", "C0_25", "C0_26", "C0_27", "C0_28", "C0_29", "C0_30", "C0_31",
322
323 "C2D0", "C2D1", "C2D2", "C2D3", "C2D4", "C2D5", "C2D6", "C2D7",
324 "C2D8", "C2D9", "C2D10", "C2D11", "C2D12", "C2D13", "C2D14", "C2D15",
325 "C2D16", "C2D17", "C2D18", "C2D19", "C2D20", "C2D21", "C2D22", "C2D23",
326 "C2D24", "C2D25", "C2D26", "C2D27", "C2D28", "C2D29", "C2D30", "C2D31",
327
328 "C2C0", "C2C1", "C2C2", "C2C3", "C2C4", "C2C5", "C2C6", "C2C7",
329 "C2C8", "C2C9", "C2C10", "C2C11", "C2C12", "C2C13", "C2C14", "C2C15",
330 "C2C16", "C2C17", "C2C18", "C2C19", "C2C20", "C2C21", "C2C22", "C2C23",
331 "C2C24", "C2C25", "C2C26", "C2C27", "C2C28", "C2C29", "C2C30", "C2C31",
332
333 "PC", "code", "cycle", "interrupt",
334};
335
336static struct {
337 int reg;
338 u32 val, val_expect;
339 u32 pc, cycle;
340} miss_log[64];
341static int miss_log_i;
342#define miss_log_len (sizeof(miss_log)/sizeof(miss_log[0]))
343#define miss_log_mask (miss_log_len-1)
344
345static void miss_log_add(int reg, u32 val, u32 val_expect, u32 pc, u32 cycle)
346{
347 miss_log[miss_log_i].reg = reg;
348 miss_log[miss_log_i].val = val;
349 miss_log[miss_log_i].val_expect = val_expect;
350 miss_log[miss_log_i].pc = pc;
351 miss_log[miss_log_i].cycle = cycle;
352 miss_log_i = (miss_log_i + 1) & miss_log_mask;
353}
354
355void breakme() {}
356
357void do_insn_cmp(void)
358{
359 static psxRegisters rregs;
360 static u32 mem_addr, mem_val;
361 u32 *allregs_p = (void *)&psxRegs;
362 u32 *allregs_e = (void *)&rregs;
363 static u32 ppc, failcount;
364 int i, ret, bad = 0;
365 u8 code;
366
367 if (f == NULL)
368 f = fopen("tracelog", "rb");
369
370 while (1) {
371 if ((ret = fread(&code, 1, 1, f)) <= 0)
372 break;
373 if (ret <= 0)
374 break;
375 if (code == 0xff)
376 break;
377 if (code == 0xfd) {
378 if ((ret = fread(&mem_addr, 1, 4, f)) <= 0)
379 break;
380 continue;
381 }
382 if (code == 0xfe) {
383 if ((ret = fread(&mem_val, 1, 4, f)) <= 0)
384 break;
385 continue;
386 }
387 if ((ret = fread(&allregs_e[code], 1, 4, f)) <= 0)
388 break;
389 }
390
391 if (ret <= 0) {
392 printf("EOF?\n");
393 goto end;
394 }
395
396 psxRegs.code = rregs.code; // don't care
397psxRegs.cycle = rregs.cycle;
398psxRegs.CP0.r[9] = rregs.CP0.r[9]; // Count
399
400//if (psxRegs.cycle == 166172) breakme();
401//if (psxRegs.cycle > 11296376) printf("pc=%08x %u %08x\n", psxRegs.pc, psxRegs.cycle, psxRegs.interrupt);
402
403 mem_addr &= 0x1ffffc;
404
405 if (memcmp(&psxRegs, &rregs, offsetof(psxRegisters, intCycle)) == 0 &&
406 mem_val == *(u32 *)(psxM + mem_addr)
407 ) {
408 failcount = 0;
409 goto ok;
410 }
411
412 for (i = 0; i < offsetof(psxRegisters, intCycle) / 4; i++) {
413 if (allregs_p[i] != allregs_e[i]) {
414 miss_log_add(i, allregs_p[i], allregs_e[i], psxRegs.pc, psxRegs.cycle);
415 bad++;
416 }
417 }
418
419 if (mem_val != *(u32 *)(psxM + mem_addr)) {
420 printf("bad mem @%08x: %08x %08x\n", mem_addr, *(u32 *)(psxM + mem_addr), mem_val);
421 goto end;
422 }
423
424 if (psxRegs.pc == rregs.pc && bad < 6 && failcount < 32) {
425 static int last_mcycle;
426 if (last_mcycle != psxRegs.cycle >> 20) {
427 printf("%u\n", psxRegs.cycle);
428 last_mcycle = psxRegs.cycle >> 20;
429 }
430 failcount++;
431 goto ok;
432 }
433
434end:
435 for (i = 0; i < miss_log_len; i++, miss_log_i = (miss_log_i + 1) & miss_log_mask)
436 printf("bad %5s: %08x %08x, pc=%08x, cycle %u\n",
437 regnames[miss_log[miss_log_i].reg], miss_log[miss_log_i].val,
438 miss_log[miss_log_i].val_expect, miss_log[miss_log_i].pc, miss_log[miss_log_i].cycle);
439 printf("-- %d\n", bad);
440 for (i = 0; i < 8; i++)
441 printf("r%d=%08x r%2d=%08x r%2d=%08x r%2d=%08x\n", i, allregs_p[i],
442 i+8, allregs_p[i+8], i+16, allregs_p[i+16], i+24, allregs_p[i+23]);
443 printf("PC: %08x/%08x, cycle %u\n", psxRegs.pc, ppc, psxRegs.cycle);
444 dump_mem("/mnt/ntz/dev/pnd/tmp/psxram.dump", psxM, 0x200000);
445 dump_mem("/mnt/ntz/dev/pnd/tmp/psxregs.dump", psxH, 0x10000);
446 exit(1);
447ok:
448 psxRegs.cycle = rregs.cycle + 2; // sync timing
449 ppc = psxRegs.pc;
450}
451
452#endif