RSP LLE plugin. Compile and run (slowly, eat 50% CPU) on the OpenPandora
[mupen64plus-pandora.git] / source / mupen64plus-rsp-z64 / src / rsp_gen.cpp
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 }