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