fc5d46b4 |
1 | /* |
2 | * z64 |
3 | * |
4 | * Copyright (C) 2007 ziggy |
5 | * |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by |
8 | * the Free Software Foundation; either version 2 of the License, or |
9 | * (at your option) any later version. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License along |
17 | * with this program; if not, write to the Free Software Foundation, Inc., |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | * |
20 | **/ |
21 | |
22 | #include "rsp.h" |
23 | #include <dlfcn.h> |
24 | #include <sys/types.h> |
25 | #include <sys/wait.h> |
26 | #include <unistd.h> |
27 | #include <assert.h> |
28 | |
29 | #define GENDEBUG |
30 | |
31 | typedef int (* gen_f)(RSP_REGS & rsp); |
32 | |
33 | struct gen_t { |
34 | UINT32 crc; |
35 | void * lib; |
36 | gen_f f; |
37 | #ifdef GENDEBUG |
38 | char name[32]; |
39 | #endif |
40 | }; |
41 | |
42 | struct opinfo_t { |
43 | int visit, labeled; |
44 | int label; |
45 | |
46 | int nbgen; |
47 | int szgen; |
48 | gen_t * gentable; |
49 | gen_t * curgen; |
50 | }; |
51 | |
52 | struct branch_t { |
53 | int start, end; |
54 | }; |
55 | |
56 | static int curvisit; |
57 | static opinfo_t opinfo[0x1000/4]; |
58 | static int nb_branches; |
59 | static branch_t branches[256]; |
60 | static int nb_labels; |
61 | static int labels[256]; |
62 | |
63 | #define OPI(pc) opinfo[(pc)>>2] |
64 | /*inline*/ void SETLABEL(int pc) { |
65 | //printf("%x\n", pc); |
66 | //pc &= 0xfff; |
67 | assert(pc >= 0 && pc < 0x1000); |
68 | if (OPI(pc).labeled != curvisit) { |
69 | labels[nb_labels] = pc; |
70 | OPI(pc).label = nb_labels++; |
71 | assert(nb_labels < sizeof(labels)/sizeof(labels[0])); |
72 | OPI(pc).labeled = curvisit; |
73 | } |
74 | } |
75 | |
76 | #define ABS(addr) (((addr) << 2) & 0xfff) |
77 | #define REL(offset) ((pc + ((offset) << 2)) & 0xfff) |
78 | |
79 | static UINT32 prep_gen(int pc, UINT32 crc, int & len) |
80 | { |
81 | UINT32 op; |
82 | int br = 0; |
83 | |
84 | branches[nb_branches].start = pc; |
85 | |
86 | while ( !br ) |
87 | { |
88 | if (OPI(pc).visit == curvisit) { |
89 | SETLABEL((pc)&0xfff); |
90 | SETLABEL((pc+4)&0xfff); |
91 | break; |
92 | } |
93 | |
94 | OPI(pc).visit = curvisit; |
95 | |
96 | op = ROPCODE(pc); |
97 | crc = ((crc<<1)|(crc>>31))^op^pc; |
98 | pc = (pc+4)&0xfff; |
99 | len++; |
100 | |
101 | switch (op >> 26) |
102 | { |
103 | case 0x00: /* SPECIAL */ |
104 | { |
105 | switch (op & 0x3f) |
106 | { |
107 | case 0x08: /* JR */ |
108 | br = 1; |
109 | break; |
110 | case 0x09: /* JALR */ |
111 | //br = 1; |
112 | break; |
113 | case 0x0d: /* BREAK */ |
114 | br = 1; |
115 | break; |
116 | } |
117 | break; |
118 | } |
119 | |
120 | case 0x01: /* REGIMM */ |
121 | { |
122 | switch (RTREG) |
123 | { |
124 | case 0x00: /* BLTZ */ |
125 | case 0x01: /* BGEZ */ |
126 | SETLABEL(REL(SIMM16)); |
127 | break; |
128 | case 0x11: /* BGEZAL */ |
129 | //br = 1; |
130 | break; |
131 | } |
132 | break; |
133 | } |
134 | |
135 | case 0x02: /* J */ |
136 | SETLABEL(ABS(UIMM26)); |
137 | br = 1; |
138 | break; |
139 | case 0x04: /* BEQ */ |
140 | case 0x05: /* BNE */ |
141 | case 0x06: /* BLEZ */ |
142 | case 0x07: /* BGTZ */ |
143 | SETLABEL(REL(SIMM16)); |
144 | break; |
145 | case 0x03: /* JAL */ |
146 | //SETLABEL(ABS(UIMM26)); |
147 | //br = 1; |
148 | break; |
149 | } |
150 | |
151 | } |
152 | |
153 | branches[nb_branches++].end = pc; |
154 | assert(nb_branches < sizeof(branches)/sizeof(branches[0])); |
155 | |
156 | return crc; |
157 | } |
158 | |
159 | static char tmps[1024]; |
160 | static char * delayed; |
161 | static int has_cond; |
162 | |
163 | #define COND \ |
164 | has_cond = 1, fprintf |
165 | |
166 | #define NOCOND() \ |
167 | if (cont && OPI((pc+4)&0xfff).labeled == curvisit) { \ |
168 | COND(fp, "cond = 1; \n"); \ |
169 | } else \ |
170 | has_cond = 0 |
171 | |
172 | |
173 | static void D_JUMP_ABS(UINT32 addr) |
174 | { |
175 | int a = addr&0xfff; |
176 | sprintf(tmps, "%s { /*if (rsp.inval_gen) { rsp.nextpc=0x%x; return 0; }*/ %s goto L%d; }", has_cond? "if (cond)":"", a, has_cond? "cond=0; ":"", OPI(a).label); |
177 | delayed = tmps; |
178 | } |
179 | |
180 | static void D_JUMP_REL(int pc, int offset) |
181 | { |
182 | D_JUMP_ABS(pc+4 + ((offset) << 2)); |
183 | } |
184 | |
185 | static void D_JUMP() |
186 | { |
187 | sprintf(tmps, "%s { return 0; }", has_cond? "if (cond)":""); |
188 | delayed = tmps; |
189 | } |
190 | |
191 | static void D_JUMPL(int pc) |
192 | { |
193 | sprintf(tmps, |
194 | "%s { \n" |
195 | "%s" |
196 | " int res;\n" |
197 | " if (res = rsp_jump(rsp.nextpc)) return res; \n" |
198 | " if (/*rsp.inval_gen || */sp_pc != 0x%x) return 0; \n" |
199 | "}", has_cond? "if (cond)":"", has_cond?" cond=0; \n":"", (pc+8)&0xfff); |
200 | delayed = tmps; |
201 | has_cond = 1; |
202 | } |
203 | |
204 | static void dogen(const char * s, UINT32 op, FILE * fp) |
205 | { |
206 | fprintf(fp, "#define op 0x%x\n%s\n#undef op\n", op, s); |
207 | } |
208 | |
209 | #define GEN(s) dogen(s, op, fp) |
210 | |
211 | static void rsp_gen(int pc) |
212 | { |
213 | int i; |
214 | const char * old_delayed; |
215 | int oldbr, br; |
216 | |
217 | curvisit++; |
218 | if (!curvisit) { |
219 | // we looped, reset all visit counters |
220 | for (i=0; i<0x1000/4; i++) { |
221 | opinfo[i].visit = 0; |
222 | opinfo[i].labeled = 0; |
223 | } |
224 | curvisit++; |
225 | } |
226 | |
227 | nb_branches = 0; |
228 | nb_labels = 0; |
229 | |
230 | int len = 0; |
231 | UINT32 crc = prep_gen(pc, 0, len); |
232 | |
233 | for (i=0; i<nb_labels; i++) { |
234 | if (OPI(labels[i]).visit != curvisit) |
235 | crc = prep_gen(labels[i], crc, len); |
236 | } |
237 | |
238 | char src[128]; |
239 | char lib[128]; |
240 | char sym[128]; |
241 | sprintf(lib, "z64/rspgen/%x-%x-%x.so", crc, pc, len); |
242 | sprintf(sym, "doit%x", crc); |
243 | |
244 | opinfo_t * opi = &OPI(pc); |
245 | if (opi->gentable) { |
246 | for (i=0; i<opi->nbgen; i++) |
247 | if (opi->gentable[i].crc == crc) { |
248 | opi->curgen = opi->gentable + i; |
249 | return; |
250 | } |
251 | } |
252 | if (opi->nbgen >= opi->szgen) { |
253 | if (opi->szgen) |
254 | opi->szgen *= 2; |
255 | else |
256 | opi->szgen = 4; |
257 | opi->gentable = (gen_t *) realloc(opi->gentable, sizeof(gen_t)*(opi->szgen)); |
258 | } |
259 | gen_t * gen; |
260 | gen = opi->gentable + opi->nbgen++; |
261 | opi->curgen = gen; |
262 | |
263 | #ifdef GENDEBUG |
264 | strcpy(gen->name, lib); |
265 | #endif |
266 | |
267 | gen->crc = crc; |
268 | gen->lib = dlopen(lib, RTLD_NOW); |
269 | if (gen->lib) { |
270 | gen->f = (gen_f) dlsym(gen->lib, sym); |
271 | assert(gen->f); |
272 | fprintf(stderr, "reloaded %s\n", lib); |
273 | return; |
274 | } |
275 | // else |
276 | // printf("%s\n", dlerror()); |
277 | |
278 | sprintf(src, "z64/rspgen/%x-%x-%x.cpp", crc, pc, len); |
279 | FILE * fp = fopen(src, "w"); |
280 | |
281 | fprintf(fp, |
282 | "#include \"rsp.h\"\n" |
283 | "\n" |
284 | "extern \"C\" {\n" |
285 | "int %s() {\n" |
286 | "int cond=0;\n", |
287 | sym); |
288 | |
289 | for (i=0; i<nb_branches; i++) { |
290 | int cont = 1; |
291 | delayed = 0; |
292 | //fprintf(stderr, "branch %x --> %x\n", branches[i].start, branches[i].end-4); |
293 | for (pc=branches[i].start; cont || delayed; pc = (pc+4)&0xfff) { |
294 | UINT32 op = ROPCODE(pc); |
295 | char s[128]; |
296 | rsp_dasm_one(s, pc, op); |
297 | if (cont && OPI(pc).labeled == curvisit) |
298 | fprintf(fp, "L%d: ;\n", OPI(pc).label); |
299 | //fprintf(fp, "/* %3x\t%s */\n", pc, s); |
300 | fprintf(fp, "GENTRACE(\"%3x\t%s\\n\");\n", pc, s); |
301 | oldbr = br; |
302 | br = 0; |
303 | old_delayed = delayed; |
304 | delayed = 0; |
305 | |
306 | if (((pc+4)&0xfff)==branches[i].end) |
307 | cont = 0; |
308 | |
309 | switch (op >> 26) |
310 | { |
311 | case 0x00: /* SPECIAL */ |
312 | { |
313 | switch (op & 0x3f) |
314 | { |
315 | case 0x08: /* JR */ |
316 | if (!old_delayed) { |
317 | br = 1|8|16; |
318 | NOCOND(); |
319 | D_JUMP(); |
320 | } |
321 | break; |
322 | case 0x09: /* JALR */ |
323 | if (!old_delayed) { |
324 | br = 1; |
325 | NOCOND(); |
326 | D_JUMPL(pc); |
327 | } |
328 | break; |
329 | case 0x0d: /* BREAK */ |
330 | br = 2|8; |
331 | //delayed = "return 1;"; |
332 | has_cond = 0; |
333 | break; |
334 | } |
335 | break; |
336 | } |
337 | |
338 | case 0x01: /* REGIMM */ |
339 | { |
340 | switch (RTREG) |
341 | { |
342 | case 0x00: /* BLTZ */ |
343 | if (!old_delayed) { |
344 | COND(fp, " cond=(INT32)(_RSVAL(0x%x)) < 0;\n", op); |
345 | D_JUMP_REL(pc, _SIMM16(op)); |
346 | br = 4; |
347 | } |
348 | break; |
349 | case 0x01: /* BGEZ */ |
350 | if (!old_delayed) { |
351 | COND(fp, " cond=(INT32)(_RSVAL(0x%x)) >= 0;\n", op); |
352 | D_JUMP_REL(pc, _SIMM16(op)); |
353 | br = 4; |
354 | } |
355 | break; |
356 | case 0x11: /* BGEZAL */ |
357 | br = 1; |
358 | COND(fp, "cond=(INT32)(_RSVAL(0x%x)) >= 0;\n", op); |
359 | D_JUMPL(pc); |
360 | break; |
361 | } |
362 | break; |
363 | } |
364 | |
365 | case 0x02: /* J */ |
366 | if (!old_delayed) { |
367 | NOCOND(); |
368 | D_JUMP_ABS(_UIMM26(op) <<2); |
369 | br = 4|8|16; |
370 | } |
371 | break; |
372 | case 0x04: /* BEQ */ |
373 | if (!old_delayed) { |
374 | COND(fp, " cond=_RSVAL(0x%0x) == _RTVAL(0x%0x);\n", op, op); |
375 | D_JUMP_REL(pc, _SIMM16(op)); |
376 | br = 4; |
377 | } |
378 | break; |
379 | case 0x05: /* BNE */ |
380 | if (!old_delayed) { |
381 | COND(fp, " cond=_RSVAL(0x%0x) != _RTVAL(0x%0x);\n", op, op); |
382 | D_JUMP_REL(pc, _SIMM16(op)); |
383 | br = 4; |
384 | } |
385 | break; |
386 | case 0x06: /* BLEZ */ |
387 | if (!old_delayed) { |
388 | COND(fp, " cond=(INT32)_RSVAL(0x%0x) <= 0;\n", op); |
389 | D_JUMP_REL(pc, _SIMM16(op)); |
390 | br = 4; |
391 | } |
392 | break; |
393 | case 0x07: /* BGTZ */ |
394 | if (!old_delayed) { |
395 | COND(fp, " cond=(INT32)_RSVAL(0x%0x) > 0;\n", op); |
396 | D_JUMP_REL(pc, _SIMM16(op)); |
397 | br = 4; |
398 | } |
399 | break; |
400 | case 0x03: /* JAL */ |
401 | if (!old_delayed) { |
402 | br = 1; |
403 | NOCOND(); |
404 | D_JUMPL(pc); |
405 | } |
406 | break; |
407 | } |
408 | |
409 | if (!(br&4) && (!old_delayed || !br)) { |
410 | if (br && !(br&16)) { |
411 | fprintf(fp, "sp_pc = 0x%x;\n", (pc + 4)&0xfff); |
412 | } |
413 | //fprintf(fp, "rsp_execute_one(0x%x);\n", op); |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | switch (op >> 26) |
420 | { |
421 | case 0x00: /* SPECIAL */ |
422 | { |
423 | switch (op & 0x3f) |
424 | { |
425 | case 0x00: /* SLL */ if (RDREG) GEN("RDVAL = (UINT32)RTVAL << SHIFT;"); break; |
426 | case 0x02: /* SRL */ if (RDREG) GEN("RDVAL = (UINT32)RTVAL >> SHIFT; "); break; |
427 | case 0x03: /* SRA */ if (RDREG) GEN("RDVAL = (INT32)RTVAL >> SHIFT; "); break; |
428 | case 0x04: /* SLLV */ if (RDREG) GEN("RDVAL = (UINT32)RTVAL << (RSVAL & 0x1f); "); break; |
429 | case 0x06: /* SRLV */ if (RDREG) GEN("RDVAL = (UINT32)RTVAL >> (RSVAL & 0x1f); "); break; |
430 | case 0x07: /* SRAV */ if (RDREG) GEN("RDVAL = (INT32)RTVAL >> (RSVAL & 0x1f); "); break; |
431 | case 0x08: /* JR */ GEN("JUMP_PC(RSVAL); "); break; |
432 | case 0x09: /* JALR */ GEN("JUMP_PC_L(RSVAL, RDREG); "); break; |
433 | case 0x0d: /* BREAK */ |
434 | { |
435 | GEN( |
436 | " \ |
437 | *z64_rspinfo.SP_STATUS_REG |= (SP_STATUS_HALT | SP_STATUS_BROKE ); \ |
438 | if ((*z64_rspinfo.SP_STATUS_REG & SP_STATUS_INTR_BREAK) != 0 ) { \ |
439 | *z64_rspinfo.MI_INTR_REG |= 1; \ |
440 | z64_rspinfo.CheckInterrupts(); \ |
441 | } \ |
442 | rsp.nextpc = ~0; \ |
443 | return 1; \ |
444 | "); |
445 | break; |
446 | } |
447 | case 0x20: /* ADD */ if (RDREG) GEN("RDVAL = (INT32)(RSVAL + RTVAL); "); break; |
448 | case 0x21: /* ADDU */ if (RDREG) GEN("RDVAL = (INT32)(RSVAL + RTVAL); "); break; |
449 | case 0x22: /* SUB */ if (RDREG) GEN("RDVAL = (INT32)(RSVAL - RTVAL); "); break; |
450 | case 0x23: /* SUBU */ if (RDREG) GEN("RDVAL = (INT32)(RSVAL - RTVAL); "); break; |
451 | case 0x24: /* AND */ if (RDREG) GEN("RDVAL = RSVAL & RTVAL; "); break; |
452 | case 0x25: /* OR */ if (RDREG) GEN("RDVAL = RSVAL | RTVAL; "); break; |
453 | case 0x26: /* XOR */ if (RDREG) GEN("RDVAL = RSVAL ^ RTVAL; "); break; |
454 | case 0x27: /* NOR */ if (RDREG) GEN("RDVAL = ~(RSVAL | RTVAL); "); break; |
455 | case 0x2a: /* SLT */ if (RDREG) GEN("RDVAL = (INT32)RSVAL < (INT32)RTVAL; "); break; |
456 | case 0x2b: /* SLTU */ if (RDREG) GEN("RDVAL = (UINT32)RSVAL < (UINT32)RTVAL; "); break; |
457 | default: GEN("unimplemented_opcode(op); "); break; |
458 | } |
459 | break; |
460 | } |
461 | |
462 | case 0x01: /* REGIMM */ |
463 | { |
464 | switch (RTREG) |
465 | { |
466 | case 0x00: /* BLTZ */ GEN("if ((INT32)(RSVAL) < 0) JUMP_REL(SIMM16); "); break; |
467 | case 0x01: /* BGEZ */ GEN("if ((INT32)(RSVAL) >= 0) JUMP_REL(SIMM16); "); break; |
468 | // VP according to the doc, link is performed even when condition fails |
469 | case 0x11: /* BGEZAL */ GEN("LINK(31); if ((INT32)(RSVAL) >= 0) JUMP_REL(SIMM16); "); break; |
470 | //case 0x11: /* BGEZAL */ if ((INT32)(RSVAL) >= 0) JUMP_REL_L(SIMM16, 31); break; |
471 | default: GEN("unimplemented_opcode(op); "); break; |
472 | } |
473 | break; |
474 | } |
475 | |
476 | case 0x02: /* J */ GEN("JUMP_ABS(UIMM26); "); break; |
477 | case 0x03: /* JAL */ GEN("JUMP_ABS_L(UIMM26, 31); "); break; |
478 | case 0x04: /* BEQ */ GEN("if (RSVAL == RTVAL) JUMP_REL(SIMM16); "); break; |
479 | case 0x05: /* BNE */ GEN("if (RSVAL != RTVAL) JUMP_REL(SIMM16); "); break; |
480 | case 0x06: /* BLEZ */ GEN("if ((INT32)RSVAL <= 0) JUMP_REL(SIMM16); "); break; |
481 | case 0x07: /* BGTZ */ GEN("if ((INT32)RSVAL > 0) JUMP_REL(SIMM16); "); break; |
482 | case 0x08: /* ADDI */ if (RTREG) GEN("RTVAL = (INT32)(RSVAL + SIMM16); "); break; |
483 | case 0x09: /* ADDIU */ if (RTREG) GEN("RTVAL = (INT32)(RSVAL + SIMM16); "); break; |
484 | case 0x0a: /* SLTI */ if (RTREG) GEN("RTVAL = (INT32)(RSVAL) < ((INT32)SIMM16); "); break; |
485 | case 0x0b: /* SLTIU */ if (RTREG) GEN("RTVAL = (UINT32)(RSVAL) < (UINT32)((INT32)SIMM16); "); break; |
486 | case 0x0c: /* ANDI */ if (RTREG) GEN("RTVAL = RSVAL & UIMM16; "); break; |
487 | case 0x0d: /* ORI */ if (RTREG) GEN("RTVAL = RSVAL | UIMM16; "); break; |
488 | case 0x0e: /* XORI */ if (RTREG) GEN("RTVAL = RSVAL ^ UIMM16; "); break; |
489 | case 0x0f: /* LUI */ if (RTREG) GEN("RTVAL = UIMM16 << 16; "); break; |
490 | |
491 | case 0x10: /* COP0 */ |
492 | { |
493 | switch ((op >> 21) & 0x1f) |
494 | { |
495 | case 0x00: /* MFC0 */ if (RTREG) GEN("RTVAL = get_cop0_reg(rsp, RDREG); "); break; |
496 | case 0x04: /* MTC0 */ |
497 | { |
498 | GEN("set_cop0_reg(rsp, RDREG, RTVAL); \n"); |
499 | if (RDREG == 0x08/4) { |
500 | fprintf(fp, |
501 | "if (rsp.inval_gen) {\n" |
502 | " rsp.inval_gen = 0;\n" |
503 | " sp_pc = 0x%x; \n" |
504 | " return 2; \n" |
505 | "}\n" |
506 | , (pc + 4)&0xfff); |
507 | } |
508 | break; |
509 | } |
510 | default: |
511 | log(M64MSG_WARNING, "unimplemented cop0 %x (%x)\n", (op >> 21) & 0x1f, op); |
512 | break; |
513 | } |
514 | break; |
515 | } |
516 | |
517 | case 0x12: /* COP2 */ |
518 | { |
519 | switch ((op >> 21) & 0x1f) |
520 | { |
521 | case 0x00: /* MFC2 */ |
522 | { |
523 | // 31 25 20 15 10 6 0 |
524 | // --------------------------------------------------- |
525 | // | 010010 | 00000 | TTTTT | DDDDD | IIII | 0000000 | |
526 | // --------------------------------------------------- |
527 | // |
528 | if (RTREG) GEN("\ |
529 | {int el = (op >> 7) & 0xf;\ |
530 | UINT16 b1 = VREG_B(VS1REG, (el+0) & 0xf);\ |
531 | UINT16 b2 = VREG_B(VS1REG, (el+1) & 0xf);\ |
532 | RTVAL = (INT32)(INT16)((b1 << 8) | (b2));}\ |
533 | "); |
534 | break; |
535 | } |
536 | case 0x02: /* CFC2 */ |
537 | { |
538 | // 31 25 20 15 10 0 |
539 | // ------------------------------------------------ |
540 | // | 010010 | 00010 | TTTTT | DDDDD | 00000000000 | |
541 | // ------------------------------------------------ |
542 | // |
543 | |
544 | // VP to sign extend or to not sign extend ? |
545 | //if (RTREG) RTVAL = (INT16)rsp.flag[RDREG]; |
546 | if (RTREG) GEN("RTVAL = rsp.flag[RDREG];"); |
547 | break; |
548 | } |
549 | case 0x04: /* MTC2 */ |
550 | { |
551 | // 31 25 20 15 10 6 0 |
552 | // --------------------------------------------------- |
553 | // | 010010 | 00100 | TTTTT | DDDDD | IIII | 0000000 | |
554 | // --------------------------------------------------- |
555 | // |
556 | GEN("\ |
557 | {int el = (op >> 7) & 0xf;\ |
558 | VREG_B(VS1REG, (el+0) & 0xf) = (RTVAL >> 8) & 0xff;\ |
559 | VREG_B(VS1REG, (el+1) & 0xf) = (RTVAL >> 0) & 0xff;}\ |
560 | "); |
561 | break; |
562 | } |
563 | case 0x06: /* CTC2 */ |
564 | { |
565 | // 31 25 20 15 10 0 |
566 | // ------------------------------------------------ |
567 | // | 010010 | 00110 | TTTTT | DDDDD | 00000000000 | |
568 | // ------------------------------------------------ |
569 | // |
570 | |
571 | GEN("rsp.flag[RDREG] = RTVAL & 0xffff;"); |
572 | break; |
573 | } |
574 | |
575 | case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: |
576 | case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: |
577 | { |
578 | GEN("handle_vector_ops(rsp, op);"); |
579 | break; |
580 | } |
581 | |
582 | default: GEN("unimplemented_opcode(op); "); break; |
583 | } |
584 | break; |
585 | } |
586 | |
587 | case 0x20: /* LB */ if (RTREG) GEN("RTVAL = (INT32)(INT8)READ8(RSVAL + SIMM16); "); break; |
588 | case 0x21: /* LH */ if (RTREG) GEN("RTVAL = (INT32)(INT16)READ16(RSVAL + SIMM16); "); break; |
589 | case 0x23: /* LW */ if (RTREG) GEN("RTVAL = READ32(RSVAL + SIMM16); "); break; |
590 | case 0x24: /* LBU */ if (RTREG) GEN("RTVAL = (UINT8)READ8(RSVAL + SIMM16); "); break; |
591 | case 0x25: /* LHU */ if (RTREG) GEN("RTVAL = (UINT16)READ16(RSVAL + SIMM16); "); break; |
592 | case 0x28: /* SB */ GEN("WRITE8(RSVAL + SIMM16, RTVAL); "); break; |
593 | case 0x29: /* SH */ GEN("WRITE16(RSVAL + SIMM16, RTVAL); "); break; |
594 | case 0x2b: /* SW */ GEN("WRITE32(RSVAL + SIMM16, RTVAL); "); break; |
595 | case 0x32: /* LWC2 */ GEN("handle_lwc2(rsp, op); "); break; |
596 | case 0x3a: /* SWC2 */ GEN("handle_swc2(rsp, op); "); break; |
597 | |
598 | default: |
599 | { |
600 | GEN("unimplemented_opcode(op);"); |
601 | break; |
602 | } |
603 | } |
604 | |
605 | |
606 | |
607 | |
608 | // if (br) { |
609 | // if (br & 2) |
610 | // fprintf(fp, "return 1;\n"); |
611 | // else |
612 | // fprintf(fp, "return 0;\n"); |
613 | // } |
614 | } |
615 | if (old_delayed) |
616 | fprintf(fp, "%s\n", old_delayed); |
617 | } |
618 | if (!((/*br|*/oldbr)&8) && ((!oldbr && !(br&2)) || has_cond)) { |
619 | fprintf(fp, "/* jumping back to %x */\ngoto L%d;\n", pc, OPI(pc).label); |
620 | assert(OPI(pc).labeled == curvisit); |
621 | } |
622 | } |
623 | |
624 | fprintf(fp, "}}\n"); |
625 | |
626 | fclose(fp); |
627 | |
628 | pid_t pid = fork(); |
629 | // SDL redirect these signals, but we need them untouched for waitpid call |
630 | signal(17, 0); |
631 | signal(11, 0); |
632 | if (!pid) { |
633 | // char s[128]; |
634 | // atexit(0); |
635 | // sprintf(s, "gcc -Iz64 -g -shared -O2 %s -o %s", src, lib); |
636 | // system(s); |
637 | // exit(0); |
638 | |
639 | //setsid(); |
640 | //execl("/usr/bin/gcc", "/usr/bin/gcc", "-Iz64", "-shared", "-g", "-O3", "-fomit-frame-pointer", src, "-o", lib, "-finline-limit=10000", 0); |
641 | //execl("/usr/bin/gcc", "/usr/bin/gcc", "-Iz64", "-shared", "-O3", src, "-o", lib, "-fomit-frame-pointer", "-ffast-math", "-funroll-loops", "-fforce-addr", "-finline-limit=10000", 0); |
642 | //execl("/usr/bin/gcc", "/usr/bin/gcc", "-Iz64", "-shared", "-O3", src, "-o", lib, "-fomit-frame-pointer", "-ffast-math", "-funroll-loops", "-fforce-addr", "-finline-limit=10000", "-m3dnow", "-mmmx", "-msse", "-msse2", "-mfpmath=sse", 0); |
643 | execl("/usr/bin/gcc", "/usr/bin/gcc", "-Iz64", "-shared", "-O6", src, "-o", lib, "-fomit-frame-pointer", "-ffast-math", "-funroll-loops", "-fforce-addr", "-finline-limit=10000", "-m3dnow", "-mmmx", "-msse", "-msse2", 0); |
644 | printf("gnii ??\n"); |
645 | exit(0); |
646 | } |
647 | waitpid(pid, 0, __WALL); |
648 | |
649 | gen->lib = dlopen(lib, RTLD_NOW); |
650 | if (!gen->lib) |
651 | log(M64MSG_WARNING, "%s\n", dlerror()); |
652 | assert(gen->lib); |
653 | log(M64MSG_VERBOSE, "created and loaded %s\n", lib); |
654 | gen->f = (gen_f) dlsym(gen->lib, sym); |
655 | assert(gen->f); |
656 | } |
657 | |
658 | void rsp_invalidate(int begin, int len) |
659 | { |
660 | //printf("invalidate %x %x\n", begin, len); |
661 | begin = 0; len = 0x1000; |
662 | assert(begin+len<=0x1000); |
663 | while (len > 0) { |
664 | OPI(begin).curgen = 0; |
665 | begin += 4; |
666 | len -= 4; |
667 | } |
668 | rsp.inval_gen = 1; |
669 | } |
670 | |
671 | int rsp_jump(int pc) |
672 | { |
673 | pc &= 0xfff; |
674 | sp_pc = pc; |
675 | rsp.nextpc = ~0; |
676 | opinfo_t * opi = &OPI(pc); |
677 | gen_t * gen = opi->curgen; |
678 | if (!gen) rsp_gen(pc); |
679 | gen = opi->curgen; |
680 | GENTRACE("rsp_jump %x (%s)\n", pc, gen->name); |
681 | int res = gen->f(rsp); |
682 | GENTRACE("r31 %x from %x nextpc %x pc %x res %d (%s)\n", rsp.r[31], pc, rsp.nextpc, sp_pc, res, gen->name); |
683 | if (rsp.nextpc != ~0) |
684 | { |
685 | sp_pc = (rsp.nextpc & 0xfff); |
686 | rsp.nextpc = ~0; |
687 | } |
688 | else |
689 | { |
690 | //sp_pc = ((sp_pc+4)&0xfff); |
691 | } |
692 | return res; |
693 | } |