RSP LLE plugin. Compile and run (slowly, eat 50% CPU) on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-rsp-z64 / src / rsp_gen.cpp
CommitLineData
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
31typedef int (* gen_f)(RSP_REGS & rsp);
32
33struct gen_t {
34 UINT32 crc;
35 void * lib;
36 gen_f f;
37#ifdef GENDEBUG
38 char name[32];
39#endif
40};
41
42struct 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
52struct branch_t {
53 int start, end;
54};
55
56static int curvisit;
57static opinfo_t opinfo[0x1000/4];
58static int nb_branches;
59static branch_t branches[256];
60static int nb_labels;
61static 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
79static 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
159static char tmps[1024];
160static char * delayed;
161static 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
173static 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
180static void D_JUMP_REL(int pc, int offset)
181{
182 D_JUMP_ABS(pc+4 + ((offset) << 2));
183}
184
185static void D_JUMP()
186{
187 sprintf(tmps, "%s { return 0; }", has_cond? "if (cond)":"");
188 delayed = tmps;
189}
190
191static 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
204static 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
211static 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
658void 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
671int 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}