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