ALL: Huge upstream synch + PerRom DelaySI & CountPerOp parameters
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / recomp.c
CommitLineData
451ab91e 1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Mupen64plus - recomp.h *
3 * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
4 * Copyright (C) 2002 Hacktarux *
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 *
17 * along with this program; if not, write to the *
18 * Free Software Foundation, Inc., *
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
20 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22#include <stdlib.h>
23#include <string.h>
24
25#if defined(__GNUC__)
26#include <unistd.h>
27#ifndef __MINGW32__
28#include <sys/mman.h>
29#endif
30#endif
31
32#include "api/m64p_types.h"
33#include "api/callbacks.h"
34#include "memory/memory.h"
35
36#include "recomp.h"
37#include "recomph.h" //include for function prototypes
38#include "macros.h"
39#include "r4300.h"
40#include "ops.h"
41
42static void *malloc_exec(size_t size);
43static void free_exec(void *ptr, size_t length);
44
45// global variables :
46precomp_instr *dst; // destination structure for the recompiled instruction
47int code_length; // current real recompiled code length
48int max_code_length; // current recompiled code's buffer length
49unsigned char **inst_pointer; // output buffer for recompiled code
50precomp_block *dst_block; // the current block that we are recompiling
51int src; // the current recompiled instruction
52int fast_memory;
53
54static void (*recomp_func)(void); // pointer to the dynarec's generator
55 // function for the latest decoded opcode
56
57#if defined(PROFILE_R4300)
58FILE *pfProfile;
59#endif
60
61static int *SRC; // currently recompiled instruction in the input stream
62static int check_nop; // next instruction is nop ?
63static int delay_slot_compiled = 0;
64
65
66
67static void RSV(void)
68{
69 dst->ops = current_instruction_table.RESERVED;
70 recomp_func = genreserved;
71}
72
73static void RFIN_BLOCK(void)
74{
75 dst->ops = current_instruction_table.FIN_BLOCK;
76 recomp_func = genfin_block;
77}
78
79static void RNOTCOMPILED(void)
80{
81 dst->ops = current_instruction_table.NOTCOMPILED;
82 recomp_func = gennotcompiled;
83}
84
85static void recompile_standard_i_type(void)
86{
87 dst->f.i.rs = reg + ((src >> 21) & 0x1F);
88 dst->f.i.rt = reg + ((src >> 16) & 0x1F);
89 dst->f.i.immediate = src & 0xFFFF;
90}
91
92static void recompile_standard_j_type(void)
93{
94 dst->f.j.inst_index = src & 0x3FFFFFF;
95}
96
97static void recompile_standard_r_type(void)
98{
99 dst->f.r.rs = reg + ((src >> 21) & 0x1F);
100 dst->f.r.rt = reg + ((src >> 16) & 0x1F);
101 dst->f.r.rd = reg + ((src >> 11) & 0x1F);
102 dst->f.r.sa = (src >> 6) & 0x1F;
103}
104
105static void recompile_standard_lf_type(void)
106{
107 dst->f.lf.base = (src >> 21) & 0x1F;
108 dst->f.lf.ft = (src >> 16) & 0x1F;
109 dst->f.lf.offset = src & 0xFFFF;
110}
111
112static void recompile_standard_cf_type(void)
113{
114 dst->f.cf.ft = (src >> 16) & 0x1F;
115 dst->f.cf.fs = (src >> 11) & 0x1F;
116 dst->f.cf.fd = (src >> 6) & 0x1F;
117}
118
119//-------------------------------------------------------------------------
120// SPECIAL
121//-------------------------------------------------------------------------
122
123static void RNOP(void)
124{
125 dst->ops = current_instruction_table.NOP;
126 recomp_func = gennop;
127}
128
129static void RSLL(void)
130{
131 dst->ops = current_instruction_table.SLL;
132 recomp_func = gensll;
133 recompile_standard_r_type();
134 if (dst->f.r.rd == reg) RNOP();
135}
136
137static void RSRL(void)
138{
139 dst->ops = current_instruction_table.SRL;
140 recomp_func = gensrl;
141 recompile_standard_r_type();
142 if (dst->f.r.rd == reg) RNOP();
143}
144
145static void RSRA(void)
146{
147 dst->ops = current_instruction_table.SRA;
148 recomp_func = gensra;
149 recompile_standard_r_type();
150 if (dst->f.r.rd == reg) RNOP();
151}
152
153static void RSLLV(void)
154{
155 dst->ops = current_instruction_table.SLLV;
156 recomp_func = gensllv;
157 recompile_standard_r_type();
158 if (dst->f.r.rd == reg) RNOP();
159}
160
161static void RSRLV(void)
162{
163 dst->ops = current_instruction_table.SRLV;
164 recomp_func = gensrlv;
165 recompile_standard_r_type();
166 if (dst->f.r.rd == reg) RNOP();
167}
168
169static void RSRAV(void)
170{
171 dst->ops = current_instruction_table.SRAV;
172 recomp_func = gensrav;
173 recompile_standard_r_type();
174 if (dst->f.r.rd == reg) RNOP();
175}
176
177static void RJR(void)
178{
179 dst->ops = current_instruction_table.JR;
180 recomp_func = genjr;
181 recompile_standard_i_type();
182}
183
184static void RJALR(void)
185{
186 dst->ops = current_instruction_table.JALR;
187 recomp_func = genjalr;
188 recompile_standard_r_type();
189}
190
191static void RSYSCALL(void)
192{
193 dst->ops = current_instruction_table.SYSCALL;
194 recomp_func = gensyscall;
195}
196
197static void RBREAK(void)
198{
199 dst->ops = current_instruction_table.NI;
200 recomp_func = genni;
201}
202
203static void RSYNC(void)
204{
205 dst->ops = current_instruction_table.SYNC;
206 recomp_func = gensync;
207}
208
209static void RMFHI(void)
210{
211 dst->ops = current_instruction_table.MFHI;
212 recomp_func = genmfhi;
213 recompile_standard_r_type();
214 if (dst->f.r.rd == reg) RNOP();
215}
216
217static void RMTHI(void)
218{
219 dst->ops = current_instruction_table.MTHI;
220 recomp_func = genmthi;
221 recompile_standard_r_type();
222}
223
224static void RMFLO(void)
225{
226 dst->ops = current_instruction_table.MFLO;
227 recomp_func = genmflo;
228 recompile_standard_r_type();
229 if (dst->f.r.rd == reg) RNOP();
230}
231
232static void RMTLO(void)
233{
234 dst->ops = current_instruction_table.MTLO;
235 recomp_func = genmtlo;
236 recompile_standard_r_type();
237}
238
239static void RDSLLV(void)
240{
241 dst->ops = current_instruction_table.DSLLV;
242 recomp_func = gendsllv;
243 recompile_standard_r_type();
244 if (dst->f.r.rd == reg) RNOP();
245}
246
247static void RDSRLV(void)
248{
249 dst->ops = current_instruction_table.DSRLV;
250 recomp_func = gendsrlv;
251 recompile_standard_r_type();
252 if (dst->f.r.rd == reg) RNOP();
253}
254
255static void RDSRAV(void)
256{
257 dst->ops = current_instruction_table.DSRAV;
258 recomp_func = gendsrav;
259 recompile_standard_r_type();
260 if (dst->f.r.rd == reg) RNOP();
261}
262
263static void RMULT(void)
264{
265 dst->ops = current_instruction_table.MULT;
266 recomp_func = genmult;
267 recompile_standard_r_type();
268}
269
270static void RMULTU(void)
271{
272 dst->ops = current_instruction_table.MULTU;
273 recomp_func = genmultu;
274 recompile_standard_r_type();
275}
276
277static void RDIV(void)
278{
279 dst->ops = current_instruction_table.DIV;
280 recomp_func = gendiv;
281 recompile_standard_r_type();
282}
283
284static void RDIVU(void)
285{
286 dst->ops = current_instruction_table.DIVU;
287 recomp_func = gendivu;
288 recompile_standard_r_type();
289}
290
291static void RDMULT(void)
292{
293 dst->ops = current_instruction_table.DMULT;
294 recomp_func = gendmult;
295 recompile_standard_r_type();
296}
297
298static void RDMULTU(void)
299{
300 dst->ops = current_instruction_table.DMULTU;
301 recomp_func = gendmultu;
302 recompile_standard_r_type();
303}
304
305static void RDDIV(void)
306{
307 dst->ops = current_instruction_table.DDIV;
308 recomp_func = genddiv;
309 recompile_standard_r_type();
310}
311
312static void RDDIVU(void)
313{
314 dst->ops = current_instruction_table.DDIVU;
315 recomp_func = genddivu;
316 recompile_standard_r_type();
317}
318
319static void RADD(void)
320{
321 dst->ops = current_instruction_table.ADD;
322 recomp_func = genadd;
323 recompile_standard_r_type();
324 if (dst->f.r.rd == reg) RNOP();
325}
326
327static void RADDU(void)
328{
329 dst->ops = current_instruction_table.ADDU;
330 recomp_func = genaddu;
331 recompile_standard_r_type();
332 if (dst->f.r.rd == reg) RNOP();
333}
334
335static void RSUB(void)
336{
337 dst->ops = current_instruction_table.SUB;
338 recomp_func = gensub;
339 recompile_standard_r_type();
340 if (dst->f.r.rd == reg) RNOP();
341}
342
343static void RSUBU(void)
344{
345 dst->ops = current_instruction_table.SUBU;
346 recomp_func = gensubu;
347 recompile_standard_r_type();
348 if (dst->f.r.rd == reg) RNOP();
349}
350
351static void RAND(void)
352{
353 dst->ops = current_instruction_table.AND;
354 recomp_func = genand;
355 recompile_standard_r_type();
356 if(dst->f.r.rd == reg) RNOP();
357}
358
359static void ROR(void)
360{
361 dst->ops = current_instruction_table.OR;
362 recomp_func = genor;
363 recompile_standard_r_type();
364 if(dst->f.r.rd == reg) RNOP();
365}
366
367static void RXOR(void)
368{
369 dst->ops = current_instruction_table.XOR;
370 recomp_func = genxor;
371 recompile_standard_r_type();
372 if(dst->f.r.rd == reg) RNOP();
373}
374
375static void RNOR(void)
376{
377 dst->ops = current_instruction_table.NOR;
378 recomp_func = gennor;
379 recompile_standard_r_type();
380 if(dst->f.r.rd == reg) RNOP();
381}
382
383static void RSLT(void)
384{
385 dst->ops = current_instruction_table.SLT;
386 recomp_func = genslt;
387 recompile_standard_r_type();
388 if(dst->f.r.rd == reg) RNOP();
389}
390
391static void RSLTU(void)
392{
393 dst->ops = current_instruction_table.SLTU;
394 recomp_func = gensltu;
395 recompile_standard_r_type();
396 if(dst->f.r.rd == reg) RNOP();
397}
398
399static void RDADD(void)
400{
401 dst->ops = current_instruction_table.DADD;
402 recomp_func = gendadd;
403 recompile_standard_r_type();
404 if (dst->f.r.rd == reg) RNOP();
405}
406
407static void RDADDU(void)
408{
409 dst->ops = current_instruction_table.DADDU;
410 recomp_func = gendaddu;
411 recompile_standard_r_type();
412 if (dst->f.r.rd == reg) RNOP();
413}
414
415static void RDSUB(void)
416{
417 dst->ops = current_instruction_table.DSUB;
418 recomp_func = gendsub;
419 recompile_standard_r_type();
420 if (dst->f.r.rd == reg) RNOP();
421}
422
423static void RDSUBU(void)
424{
425 dst->ops = current_instruction_table.DSUBU;
426 recomp_func = gendsubu;
427 recompile_standard_r_type();
428 if (dst->f.r.rd == reg) RNOP();
429}
430
431static void RTGE(void)
432{
433 dst->ops = current_instruction_table.NI;
434 recomp_func = genni;
435}
436
437static void RTGEU(void)
438{
439 dst->ops = current_instruction_table.NI;
440 recomp_func = genni;
441}
442
443static void RTLT(void)
444{
445 dst->ops = current_instruction_table.NI;
446 recomp_func = genni;
447}
448
449static void RTLTU(void)
450{
451 dst->ops = current_instruction_table.NI;
452 recomp_func = genni;
453}
454
455static void RTEQ(void)
456{
457 dst->ops = current_instruction_table.TEQ;
458 recomp_func = genteq;
459 recompile_standard_r_type();
460}
461
462static void RTNE(void)
463{
464 dst->ops = current_instruction_table.NI;
465 recomp_func = genni;
466}
467
468static void RDSLL(void)
469{
470 dst->ops = current_instruction_table.DSLL;
471 recomp_func = gendsll;
472 recompile_standard_r_type();
473 if (dst->f.r.rd == reg) RNOP();
474}
475
476static void RDSRL(void)
477{
478 dst->ops = current_instruction_table.DSRL;
479 recomp_func = gendsrl;
480 recompile_standard_r_type();
481 if (dst->f.r.rd == reg) RNOP();
482}
483
484static void RDSRA(void)
485{
486 dst->ops = current_instruction_table.DSRA;
487 recomp_func = gendsra;
488 recompile_standard_r_type();
489 if (dst->f.r.rd == reg) RNOP();
490}
491
492static void RDSLL32(void)
493{
494 dst->ops = current_instruction_table.DSLL32;
495 recomp_func = gendsll32;
496 recompile_standard_r_type();
497 if (dst->f.r.rd == reg) RNOP();
498}
499
500static void RDSRL32(void)
501{
502 dst->ops = current_instruction_table.DSRL32;
503 recomp_func = gendsrl32;
504 recompile_standard_r_type();
505 if (dst->f.r.rd == reg) RNOP();
506}
507
508static void RDSRA32(void)
509{
510 dst->ops = current_instruction_table.DSRA32;
511 recomp_func = gendsra32;
512 recompile_standard_r_type();
513 if (dst->f.r.rd == reg) RNOP();
514}
515
516static void (*recomp_special[64])(void) =
517{
518 RSLL , RSV , RSRL , RSRA , RSLLV , RSV , RSRLV , RSRAV ,
519 RJR , RJALR , RSV , RSV , RSYSCALL, RBREAK , RSV , RSYNC ,
520 RMFHI, RMTHI , RMFLO, RMTLO, RDSLLV , RSV , RDSRLV , RDSRAV ,
521 RMULT, RMULTU, RDIV , RDIVU, RDMULT , RDMULTU, RDDIV , RDDIVU ,
522 RADD , RADDU , RSUB , RSUBU, RAND , ROR , RXOR , RNOR ,
523 RSV , RSV , RSLT , RSLTU, RDADD , RDADDU , RDSUB , RDSUBU ,
524 RTGE , RTGEU , RTLT , RTLTU, RTEQ , RSV , RTNE , RSV ,
525 RDSLL, RSV , RDSRL, RDSRA, RDSLL32 , RSV , RDSRL32, RDSRA32
526};
527
528//-------------------------------------------------------------------------
529// REGIMM
530//-------------------------------------------------------------------------
531
532static void RBLTZ(void)
533{
534 unsigned int target;
535 dst->ops = current_instruction_table.BLTZ;
536 recomp_func = genbltz;
537 recompile_standard_i_type();
538 target = dst->addr + dst->f.i.immediate*4 + 4;
539 if (target == dst->addr)
540 {
541 if (check_nop)
542 {
543 dst->ops = current_instruction_table.BLTZ_IDLE;
544 recomp_func = genbltz_idle;
545 }
546 }
547 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
548 {
549 dst->ops = current_instruction_table.BLTZ_OUT;
550 recomp_func = genbltz_out;
551 }
552}
553
554static void RBGEZ(void)
555{
556 unsigned int target;
557 dst->ops = current_instruction_table.BGEZ;
558 recomp_func = genbgez;
559 recompile_standard_i_type();
560 target = dst->addr + dst->f.i.immediate*4 + 4;
561 if (target == dst->addr)
562 {
563 if (check_nop)
564 {
565 dst->ops = current_instruction_table.BGEZ_IDLE;
566 recomp_func = genbgez_idle;
567 }
568 }
569 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
570 {
571 dst->ops = current_instruction_table.BGEZ_OUT;
572 recomp_func = genbgez_out;
573 }
574}
575
576static void RBLTZL(void)
577{
578 unsigned int target;
579 dst->ops = current_instruction_table.BLTZL;
580 recomp_func = genbltzl;
581 recompile_standard_i_type();
582 target = dst->addr + dst->f.i.immediate*4 + 4;
583 if (target == dst->addr)
584 {
585 if (check_nop)
586 {
587 dst->ops = current_instruction_table.BLTZL_IDLE;
588 recomp_func = genbltzl_idle;
589 }
590 }
591 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
592 {
593 dst->ops = current_instruction_table.BLTZL_OUT;
594 recomp_func = genbltzl_out;
595 }
596}
597
598static void RBGEZL(void)
599{
600 unsigned int target;
601 dst->ops = current_instruction_table.BGEZL;
602 recomp_func = genbgezl;
603 recompile_standard_i_type();
604 target = dst->addr + dst->f.i.immediate*4 + 4;
605 if (target == dst->addr)
606 {
607 if (check_nop)
608 {
609 dst->ops = current_instruction_table.BGEZL_IDLE;
610 recomp_func = genbgezl_idle;
611 }
612 }
613 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
614 {
615 dst->ops = current_instruction_table.BGEZL_OUT;
616 recomp_func = genbgezl_out;
617 }
618}
619
620static void RTGEI(void)
621{
622 dst->ops = current_instruction_table.NI;
623 recomp_func = genni;
624}
625
626static void RTGEIU(void)
627{
628 dst->ops = current_instruction_table.NI;
629 recomp_func = genni;
630}
631
632static void RTLTI(void)
633{
634 dst->ops = current_instruction_table.NI;
635 recomp_func = genni;
636}
637
638static void RTLTIU(void)
639{
640 dst->ops = current_instruction_table.NI;
641 recomp_func = genni;
642}
643
644static void RTEQI(void)
645{
646 dst->ops = current_instruction_table.NI;
647 recomp_func = genni;
648}
649
650static void RTNEI(void)
651{
652 dst->ops = current_instruction_table.NI;
653 recomp_func = genni;
654}
655
656static void RBLTZAL(void)
657{
658 unsigned int target;
659 dst->ops = current_instruction_table.BLTZAL;
660 recomp_func = genbltzal;
661 recompile_standard_i_type();
662 target = dst->addr + dst->f.i.immediate*4 + 4;
663 if (target == dst->addr)
664 {
665 if (check_nop)
666 {
667 dst->ops = current_instruction_table.BLTZAL_IDLE;
668 recomp_func = genbltzal_idle;
669 }
670 }
671 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
672 {
673 dst->ops = current_instruction_table.BLTZAL_OUT;
674 recomp_func = genbltzal_out;
675 }
676}
677
678static void RBGEZAL(void)
679{
680 unsigned int target;
681 dst->ops = current_instruction_table.BGEZAL;
682 recomp_func = genbgezal;
683 recompile_standard_i_type();
684 target = dst->addr + dst->f.i.immediate*4 + 4;
685 if (target == dst->addr)
686 {
687 if (check_nop)
688 {
689 dst->ops = current_instruction_table.BGEZAL_IDLE;
690 recomp_func = genbgezal_idle;
691 }
692 }
693 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
694 {
695 dst->ops = current_instruction_table.BGEZAL_OUT;
696 recomp_func = genbgezal_out;
697 }
698}
699
700static void RBLTZALL(void)
701{
702 unsigned int target;
703 dst->ops = current_instruction_table.BLTZALL;
704 recomp_func = genbltzall;
705 recompile_standard_i_type();
706 target = dst->addr + dst->f.i.immediate*4 + 4;
707 if (target == dst->addr)
708 {
709 if (check_nop)
710 {
711 dst->ops = current_instruction_table.BLTZALL_IDLE;
712 recomp_func = genbltzall_idle;
713 }
714 }
715 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
716 {
717 dst->ops = current_instruction_table.BLTZALL_OUT;
718 recomp_func = genbltzall_out;
719 }
720}
721
722static void RBGEZALL(void)
723{
724 unsigned int target;
725 dst->ops = current_instruction_table.BGEZALL;
726 recomp_func = genbgezall;
727 recompile_standard_i_type();
728 target = dst->addr + dst->f.i.immediate*4 + 4;
729 if (target == dst->addr)
730 {
731 if (check_nop)
732 {
733 dst->ops = current_instruction_table.BGEZALL_IDLE;
734 recomp_func = genbgezall_idle;
735 }
736 }
737 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
738 {
739 dst->ops = current_instruction_table.BGEZALL_OUT;
740 recomp_func = genbgezall_out;
741 }
742}
743
744static void (*recomp_regimm[32])(void) =
745{
746 RBLTZ , RBGEZ , RBLTZL , RBGEZL , RSV , RSV, RSV , RSV,
747 RTGEI , RTGEIU , RTLTI , RTLTIU , RTEQI, RSV, RTNEI, RSV,
748 RBLTZAL, RBGEZAL, RBLTZALL, RBGEZALL, RSV , RSV, RSV , RSV,
749 RSV , RSV , RSV , RSV , RSV , RSV, RSV , RSV
750};
751
752//-------------------------------------------------------------------------
753// TLB
754//-------------------------------------------------------------------------
755
756static void RTLBR(void)
757{
758 dst->ops = current_instruction_table.TLBR;
759 recomp_func = gentlbr;
760}
761
762static void RTLBWI(void)
763{
764 dst->ops = current_instruction_table.TLBWI;
765 recomp_func = gentlbwi;
766}
767
768static void RTLBWR(void)
769{
770 dst->ops = current_instruction_table.TLBWR;
771 recomp_func = gentlbwr;
772}
773
774static void RTLBP(void)
775{
776 dst->ops = current_instruction_table.TLBP;
777 recomp_func = gentlbp;
778}
779
780static void RERET(void)
781{
782 dst->ops = current_instruction_table.ERET;
783 recomp_func = generet;
784}
785
786static void (*recomp_tlb[64])(void) =
787{
788 RSV , RTLBR, RTLBWI, RSV, RSV, RSV, RTLBWR, RSV,
789 RTLBP, RSV , RSV , RSV, RSV, RSV, RSV , RSV,
790 RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,
791 RERET, RSV , RSV , RSV, RSV, RSV, RSV , RSV,
792 RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,
793 RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,
794 RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV,
795 RSV , RSV , RSV , RSV, RSV, RSV, RSV , RSV
796};
797
798//-------------------------------------------------------------------------
799// COP0
800//-------------------------------------------------------------------------
801
802static void RMFC0(void)
803{
804 dst->ops = current_instruction_table.MFC0;
805 recomp_func = genmfc0;
806 recompile_standard_r_type();
807 dst->f.r.rd = (long long*)(reg_cop0 + ((src >> 11) & 0x1F));
808 dst->f.r.nrd = (src >> 11) & 0x1F;
809 if (dst->f.r.rt == reg) RNOP();
810}
811
812static void RMTC0(void)
813{
814 dst->ops = current_instruction_table.MTC0;
815 recomp_func = genmtc0;
816 recompile_standard_r_type();
817 dst->f.r.nrd = (src >> 11) & 0x1F;
818}
819
820static void RTLB(void)
821{
822 recomp_tlb[(src & 0x3F)]();
823}
824
825static void (*recomp_cop0[32])(void) =
826{
827 RMFC0, RSV, RSV, RSV, RMTC0, RSV, RSV, RSV,
828 RSV , RSV, RSV, RSV, RSV , RSV, RSV, RSV,
829 RTLB , RSV, RSV, RSV, RSV , RSV, RSV, RSV,
830 RSV , RSV, RSV, RSV, RSV , RSV, RSV, RSV
831};
832
833//-------------------------------------------------------------------------
834// BC
835//-------------------------------------------------------------------------
836
837static void RBC1F(void)
838{
839 unsigned int target;
840 dst->ops = current_instruction_table.BC1F;
841 recomp_func = genbc1f;
842 recompile_standard_i_type();
843 target = dst->addr + dst->f.i.immediate*4 + 4;
844 if (target == dst->addr)
845 {
846 if (check_nop)
847 {
848 dst->ops = current_instruction_table.BC1F_IDLE;
849 recomp_func = genbc1f_idle;
850 }
851 }
852 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
853 {
854 dst->ops = current_instruction_table.BC1F_OUT;
855 recomp_func = genbc1f_out;
856 }
857}
858
859static void RBC1T(void)
860{
861 unsigned int target;
862 dst->ops = current_instruction_table.BC1T;
863 recomp_func = genbc1t;
864 recompile_standard_i_type();
865 target = dst->addr + dst->f.i.immediate*4 + 4;
866 if (target == dst->addr)
867 {
868 if (check_nop)
869 {
870 dst->ops = current_instruction_table.BC1T_IDLE;
871 recomp_func = genbc1t_idle;
872 }
873 }
874 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
875 {
876 dst->ops = current_instruction_table.BC1T_OUT;
877 recomp_func = genbc1t_out;
878 }
879}
880
881static void RBC1FL(void)
882{
883 unsigned int target;
884 dst->ops = current_instruction_table.BC1FL;
885 recomp_func = genbc1fl;
886 recompile_standard_i_type();
887 target = dst->addr + dst->f.i.immediate*4 + 4;
888 if (target == dst->addr)
889 {
890 if (check_nop)
891 {
892 dst->ops = current_instruction_table.BC1FL_IDLE;
893 recomp_func = genbc1fl_idle;
894 }
895 }
896 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
897 {
898 dst->ops = current_instruction_table.BC1FL_OUT;
899 recomp_func = genbc1fl_out;
900 }
901}
902
903static void RBC1TL(void)
904{
905 unsigned int target;
906 dst->ops = current_instruction_table.BC1TL;
907 recomp_func = genbc1tl;
908 recompile_standard_i_type();
909 target = dst->addr + dst->f.i.immediate*4 + 4;
910 if (target == dst->addr)
911 {
912 if (check_nop)
913 {
914 dst->ops = current_instruction_table.BC1TL_IDLE;
915 recomp_func = genbc1tl_idle;
916 }
917 }
918 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
919 {
920 dst->ops = current_instruction_table.BC1TL_OUT;
921 recomp_func = genbc1tl_out;
922 }
923}
924
925static void (*recomp_bc[4])(void) =
926{
927 RBC1F , RBC1T ,
928 RBC1FL, RBC1TL
929};
930
931//-------------------------------------------------------------------------
932// S
933//-------------------------------------------------------------------------
934
935static void RADD_S(void)
936{
937 dst->ops = current_instruction_table.ADD_S;
938 recomp_func = genadd_s;
939 recompile_standard_cf_type();
940}
941
942static void RSUB_S(void)
943{
944 dst->ops = current_instruction_table.SUB_S;
945 recomp_func = gensub_s;
946 recompile_standard_cf_type();
947}
948
949static void RMUL_S(void)
950{
951 dst->ops = current_instruction_table.MUL_S;
952 recomp_func = genmul_s;
953 recompile_standard_cf_type();
954}
955
956static void RDIV_S(void)
957{
958 dst->ops = current_instruction_table.DIV_S;
959 recomp_func = gendiv_s;
960 recompile_standard_cf_type();
961}
962
963static void RSQRT_S(void)
964{
965 dst->ops = current_instruction_table.SQRT_S;
966 recomp_func = gensqrt_s;
967 recompile_standard_cf_type();
968}
969
970static void RABS_S(void)
971{
972 dst->ops = current_instruction_table.ABS_S;
973 recomp_func = genabs_s;
974 recompile_standard_cf_type();
975}
976
977static void RMOV_S(void)
978{
979 dst->ops = current_instruction_table.MOV_S;
980 recomp_func = genmov_s;
981 recompile_standard_cf_type();
982}
983
984static void RNEG_S(void)
985{
986 dst->ops = current_instruction_table.NEG_S;
987 recomp_func = genneg_s;
988 recompile_standard_cf_type();
989}
990
991static void RROUND_L_S(void)
992{
993 dst->ops = current_instruction_table.ROUND_L_S;
994 recomp_func = genround_l_s;
995 recompile_standard_cf_type();
996}
997
998static void RTRUNC_L_S(void)
999{
1000 dst->ops = current_instruction_table.TRUNC_L_S;
1001 recomp_func = gentrunc_l_s;
1002 recompile_standard_cf_type();
1003}
1004
1005static void RCEIL_L_S(void)
1006{
1007 dst->ops = current_instruction_table.CEIL_L_S;
1008 recomp_func = genceil_l_s;
1009 recompile_standard_cf_type();
1010}
1011
1012static void RFLOOR_L_S(void)
1013{
1014 dst->ops = current_instruction_table.FLOOR_L_S;
1015 recomp_func = genfloor_l_s;
1016 recompile_standard_cf_type();
1017}
1018
1019static void RROUND_W_S(void)
1020{
1021 dst->ops = current_instruction_table.ROUND_W_S;
1022 recomp_func = genround_w_s;
1023 recompile_standard_cf_type();
1024}
1025
1026static void RTRUNC_W_S(void)
1027{
1028 dst->ops = current_instruction_table.TRUNC_W_S;
1029 recomp_func = gentrunc_w_s;
1030 recompile_standard_cf_type();
1031}
1032
1033static void RCEIL_W_S(void)
1034{
1035 dst->ops = current_instruction_table.CEIL_W_S;
1036 recomp_func = genceil_w_s;
1037 recompile_standard_cf_type();
1038}
1039
1040static void RFLOOR_W_S(void)
1041{
1042 dst->ops = current_instruction_table.FLOOR_W_S;
1043 recomp_func = genfloor_w_s;
1044 recompile_standard_cf_type();
1045}
1046
1047static void RCVT_D_S(void)
1048{
1049 dst->ops = current_instruction_table.CVT_D_S;
1050 recomp_func = gencvt_d_s;
1051 recompile_standard_cf_type();
1052}
1053
1054static void RCVT_W_S(void)
1055{
1056 dst->ops = current_instruction_table.CVT_W_S;
1057 recomp_func = gencvt_w_s;
1058 recompile_standard_cf_type();
1059}
1060
1061static void RCVT_L_S(void)
1062{
1063 dst->ops = current_instruction_table.CVT_L_S;
1064 recomp_func = gencvt_l_s;
1065 recompile_standard_cf_type();
1066}
1067
1068static void RC_F_S(void)
1069{
1070 dst->ops = current_instruction_table.C_F_S;
1071 recomp_func = genc_f_s;
1072 recompile_standard_cf_type();
1073}
1074
1075static void RC_UN_S(void)
1076{
1077 dst->ops = current_instruction_table.C_UN_S;
1078 recomp_func = genc_un_s;
1079 recompile_standard_cf_type();
1080}
1081
1082static void RC_EQ_S(void)
1083{
1084 dst->ops = current_instruction_table.C_EQ_S;
1085 recomp_func = genc_eq_s;
1086 recompile_standard_cf_type();
1087}
1088
1089static void RC_UEQ_S(void)
1090{
1091 dst->ops = current_instruction_table.C_UEQ_S;
1092 recomp_func = genc_ueq_s;
1093 recompile_standard_cf_type();
1094}
1095
1096static void RC_OLT_S(void)
1097{
1098 dst->ops = current_instruction_table.C_OLT_S;
1099 recomp_func = genc_olt_s;
1100 recompile_standard_cf_type();
1101}
1102
1103static void RC_ULT_S(void)
1104{
1105 dst->ops = current_instruction_table.C_ULT_S;
1106 recomp_func = genc_ult_s;
1107 recompile_standard_cf_type();
1108}
1109
1110static void RC_OLE_S(void)
1111{
1112 dst->ops = current_instruction_table.C_OLE_S;
1113 recomp_func = genc_ole_s;
1114 recompile_standard_cf_type();
1115}
1116
1117static void RC_ULE_S(void)
1118{
1119 dst->ops = current_instruction_table.C_ULE_S;
1120 recomp_func = genc_ule_s;
1121 recompile_standard_cf_type();
1122}
1123
1124static void RC_SF_S(void)
1125{
1126 dst->ops = current_instruction_table.C_SF_S;
1127 recomp_func = genc_sf_s;
1128 recompile_standard_cf_type();
1129}
1130
1131static void RC_NGLE_S(void)
1132{
1133 dst->ops = current_instruction_table.C_NGLE_S;
1134 recomp_func = genc_ngle_s;
1135 recompile_standard_cf_type();
1136}
1137
1138static void RC_SEQ_S(void)
1139{
1140 dst->ops = current_instruction_table.C_SEQ_S;
1141 recomp_func = genc_seq_s;
1142 recompile_standard_cf_type();
1143}
1144
1145static void RC_NGL_S(void)
1146{
1147 dst->ops = current_instruction_table.C_NGL_S;
1148 recomp_func = genc_ngl_s;
1149 recompile_standard_cf_type();
1150}
1151
1152static void RC_LT_S(void)
1153{
1154 dst->ops = current_instruction_table.C_LT_S;
1155 recomp_func = genc_lt_s;
1156 recompile_standard_cf_type();
1157}
1158
1159static void RC_NGE_S(void)
1160{
1161 dst->ops = current_instruction_table.C_NGE_S;
1162 recomp_func = genc_nge_s;
1163 recompile_standard_cf_type();
1164}
1165
1166static void RC_LE_S(void)
1167{
1168 dst->ops = current_instruction_table.C_LE_S;
1169 recomp_func = genc_le_s;
1170 recompile_standard_cf_type();
1171}
1172
1173static void RC_NGT_S(void)
1174{
1175 dst->ops = current_instruction_table.C_NGT_S;
1176 recomp_func = genc_ngt_s;
1177 recompile_standard_cf_type();
1178}
1179
1180static void (*recomp_s[64])(void) =
1181{
1182 RADD_S , RSUB_S , RMUL_S , RDIV_S , RSQRT_S , RABS_S , RMOV_S , RNEG_S ,
1183 RROUND_L_S, RTRUNC_L_S, RCEIL_L_S, RFLOOR_L_S, RROUND_W_S, RTRUNC_W_S, RCEIL_W_S, RFLOOR_W_S,
1184 RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,
1185 RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,
1186 RSV , RCVT_D_S , RSV , RSV , RCVT_W_S , RCVT_L_S , RSV , RSV ,
1187 RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,
1188 RC_F_S , RC_UN_S , RC_EQ_S , RC_UEQ_S , RC_OLT_S , RC_ULT_S , RC_OLE_S , RC_ULE_S ,
1189 RC_SF_S , RC_NGLE_S , RC_SEQ_S , RC_NGL_S , RC_LT_S , RC_NGE_S , RC_LE_S , RC_NGT_S
1190};
1191
1192//-------------------------------------------------------------------------
1193// D
1194//-------------------------------------------------------------------------
1195
1196static void RADD_D(void)
1197{
1198 dst->ops = current_instruction_table.ADD_D;
1199 recomp_func = genadd_d;
1200 recompile_standard_cf_type();
1201}
1202
1203static void RSUB_D(void)
1204{
1205 dst->ops = current_instruction_table.SUB_D;
1206 recomp_func = gensub_d;
1207 recompile_standard_cf_type();
1208}
1209
1210static void RMUL_D(void)
1211{
1212 dst->ops = current_instruction_table.MUL_D;
1213 recomp_func = genmul_d;
1214 recompile_standard_cf_type();
1215}
1216
1217static void RDIV_D(void)
1218{
1219 dst->ops = current_instruction_table.DIV_D;
1220 recomp_func = gendiv_d;
1221 recompile_standard_cf_type();
1222}
1223
1224static void RSQRT_D(void)
1225{
1226 dst->ops = current_instruction_table.SQRT_D;
1227 recomp_func = gensqrt_d;
1228 recompile_standard_cf_type();
1229}
1230
1231static void RABS_D(void)
1232{
1233 dst->ops = current_instruction_table.ABS_D;
1234 recomp_func = genabs_d;
1235 recompile_standard_cf_type();
1236}
1237
1238static void RMOV_D(void)
1239{
1240 dst->ops = current_instruction_table.MOV_D;
1241 recomp_func = genmov_d;
1242 recompile_standard_cf_type();
1243}
1244
1245static void RNEG_D(void)
1246{
1247 dst->ops = current_instruction_table.NEG_D;
1248 recomp_func = genneg_d;
1249 recompile_standard_cf_type();
1250}
1251
1252static void RROUND_L_D(void)
1253{
1254 dst->ops = current_instruction_table.ROUND_L_D;
1255 recomp_func = genround_l_d;
1256 recompile_standard_cf_type();
1257}
1258
1259static void RTRUNC_L_D(void)
1260{
1261 dst->ops = current_instruction_table.TRUNC_L_D;
1262 recomp_func = gentrunc_l_d;
1263 recompile_standard_cf_type();
1264}
1265
1266static void RCEIL_L_D(void)
1267{
1268 dst->ops = current_instruction_table.CEIL_L_D;
1269 recomp_func = genceil_l_d;
1270 recompile_standard_cf_type();
1271}
1272
1273static void RFLOOR_L_D(void)
1274{
1275 dst->ops = current_instruction_table.FLOOR_L_D;
1276 recomp_func = genfloor_l_d;
1277 recompile_standard_cf_type();
1278}
1279
1280static void RROUND_W_D(void)
1281{
1282 dst->ops = current_instruction_table.ROUND_W_D;
1283 recomp_func = genround_w_d;
1284 recompile_standard_cf_type();
1285}
1286
1287static void RTRUNC_W_D(void)
1288{
1289 dst->ops = current_instruction_table.TRUNC_W_D;
1290 recomp_func = gentrunc_w_d;
1291 recompile_standard_cf_type();
1292}
1293
1294static void RCEIL_W_D(void)
1295{
1296 dst->ops = current_instruction_table.CEIL_W_D;
1297 recomp_func = genceil_w_d;
1298 recompile_standard_cf_type();
1299}
1300
1301static void RFLOOR_W_D(void)
1302{
1303 dst->ops = current_instruction_table.FLOOR_W_D;
1304 recomp_func = genfloor_w_d;
1305 recompile_standard_cf_type();
1306}
1307
1308static void RCVT_S_D(void)
1309{
1310 dst->ops = current_instruction_table.CVT_S_D;
1311 recomp_func = gencvt_s_d;
1312 recompile_standard_cf_type();
1313}
1314
1315static void RCVT_W_D(void)
1316{
1317 dst->ops = current_instruction_table.CVT_W_D;
1318 recomp_func = gencvt_w_d;
1319 recompile_standard_cf_type();
1320}
1321
1322static void RCVT_L_D(void)
1323{
1324 dst->ops = current_instruction_table.CVT_L_D;
1325 recomp_func = gencvt_l_d;
1326 recompile_standard_cf_type();
1327}
1328
1329static void RC_F_D(void)
1330{
1331 dst->ops = current_instruction_table.C_F_D;
1332 recomp_func = genc_f_d;
1333 recompile_standard_cf_type();
1334}
1335
1336static void RC_UN_D(void)
1337{
1338 dst->ops = current_instruction_table.C_UN_D;
1339 recomp_func = genc_un_d;
1340 recompile_standard_cf_type();
1341}
1342
1343static void RC_EQ_D(void)
1344{
1345 dst->ops = current_instruction_table.C_EQ_D;
1346 recomp_func = genc_eq_d;
1347 recompile_standard_cf_type();
1348}
1349
1350static void RC_UEQ_D(void)
1351{
1352 dst->ops = current_instruction_table.C_UEQ_D;
1353 recomp_func = genc_ueq_d;
1354 recompile_standard_cf_type();
1355}
1356
1357static void RC_OLT_D(void)
1358{
1359 dst->ops = current_instruction_table.C_OLT_D;
1360 recomp_func = genc_olt_d;
1361 recompile_standard_cf_type();
1362}
1363
1364static void RC_ULT_D(void)
1365{
1366 dst->ops = current_instruction_table.C_ULT_D;
1367 recomp_func = genc_ult_d;
1368 recompile_standard_cf_type();
1369}
1370
1371static void RC_OLE_D(void)
1372{
1373 dst->ops = current_instruction_table.C_OLE_D;
1374 recomp_func = genc_ole_d;
1375 recompile_standard_cf_type();
1376}
1377
1378static void RC_ULE_D(void)
1379{
1380 dst->ops = current_instruction_table.C_ULE_D;
1381 recomp_func = genc_ule_d;
1382 recompile_standard_cf_type();
1383}
1384
1385static void RC_SF_D(void)
1386{
1387 dst->ops = current_instruction_table.C_SF_D;
1388 recomp_func = genc_sf_d;
1389 recompile_standard_cf_type();
1390}
1391
1392static void RC_NGLE_D(void)
1393{
1394 dst->ops = current_instruction_table.C_NGLE_D;
1395 recomp_func = genc_ngle_d;
1396 recompile_standard_cf_type();
1397}
1398
1399static void RC_SEQ_D(void)
1400{
1401 dst->ops = current_instruction_table.C_SEQ_D;
1402 recomp_func = genc_seq_d;
1403 recompile_standard_cf_type();
1404}
1405
1406static void RC_NGL_D(void)
1407{
1408 dst->ops = current_instruction_table.C_NGL_D;
1409 recomp_func = genc_ngl_d;
1410 recompile_standard_cf_type();
1411}
1412
1413static void RC_LT_D(void)
1414{
1415 dst->ops = current_instruction_table.C_LT_D;
1416 recomp_func = genc_lt_d;
1417 recompile_standard_cf_type();
1418}
1419
1420static void RC_NGE_D(void)
1421{
1422 dst->ops = current_instruction_table.C_NGE_D;
1423 recomp_func = genc_nge_d;
1424 recompile_standard_cf_type();
1425}
1426
1427static void RC_LE_D(void)
1428{
1429 dst->ops = current_instruction_table.C_LE_D;
1430 recomp_func = genc_le_d;
1431 recompile_standard_cf_type();
1432}
1433
1434static void RC_NGT_D(void)
1435{
1436 dst->ops = current_instruction_table.C_NGT_D;
1437 recomp_func = genc_ngt_d;
1438 recompile_standard_cf_type();
1439}
1440
1441static void (*recomp_d[64])(void) =
1442{
1443 RADD_D , RSUB_D , RMUL_D , RDIV_D , RSQRT_D , RABS_D , RMOV_D , RNEG_D ,
1444 RROUND_L_D, RTRUNC_L_D, RCEIL_L_D, RFLOOR_L_D, RROUND_W_D, RTRUNC_W_D, RCEIL_W_D, RFLOOR_W_D,
1445 RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,
1446 RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,
1447 RCVT_S_D , RSV , RSV , RSV , RCVT_W_D , RCVT_L_D , RSV , RSV ,
1448 RSV , RSV , RSV , RSV , RSV , RSV , RSV , RSV ,
1449 RC_F_D , RC_UN_D , RC_EQ_D , RC_UEQ_D , RC_OLT_D , RC_ULT_D , RC_OLE_D , RC_ULE_D ,
1450 RC_SF_D , RC_NGLE_D , RC_SEQ_D , RC_NGL_D , RC_LT_D , RC_NGE_D , RC_LE_D , RC_NGT_D
1451};
1452
1453//-------------------------------------------------------------------------
1454// W
1455//-------------------------------------------------------------------------
1456
1457static void RCVT_S_W(void)
1458{
1459 dst->ops = current_instruction_table.CVT_S_W;
1460 recomp_func = gencvt_s_w;
1461 recompile_standard_cf_type();
1462}
1463
1464static void RCVT_D_W(void)
1465{
1466 dst->ops = current_instruction_table.CVT_D_W;
1467 recomp_func = gencvt_d_w;
1468 recompile_standard_cf_type();
1469}
1470
1471static void (*recomp_w[64])(void) =
1472{
1473 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1474 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1475 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1476 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1477 RCVT_S_W, RCVT_D_W, RSV, RSV, RSV, RSV, RSV, RSV,
1478 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1479 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1480 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV
1481};
1482
1483//-------------------------------------------------------------------------
1484// L
1485//-------------------------------------------------------------------------
1486
1487static void RCVT_S_L(void)
1488{
1489 dst->ops = current_instruction_table.CVT_S_L;
1490 recomp_func = gencvt_s_l;
1491 recompile_standard_cf_type();
1492}
1493
1494static void RCVT_D_L(void)
1495{
1496 dst->ops = current_instruction_table.CVT_D_L;
1497 recomp_func = gencvt_d_l;
1498 recompile_standard_cf_type();
1499}
1500
1501static void (*recomp_l[64])(void) =
1502{
1503 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1504 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1505 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1506 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1507 RCVT_S_L, RCVT_D_L, RSV, RSV, RSV, RSV, RSV, RSV,
1508 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1509 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1510 RSV , RSV , RSV, RSV, RSV, RSV, RSV, RSV,
1511};
1512
1513//-------------------------------------------------------------------------
1514// COP1
1515//-------------------------------------------------------------------------
1516
1517static void RMFC1(void)
1518{
1519 dst->ops = current_instruction_table.MFC1;
1520 recomp_func = genmfc1;
1521 recompile_standard_r_type();
1522 dst->f.r.nrd = (src >> 11) & 0x1F;
1523 if (dst->f.r.rt == reg) RNOP();
1524}
1525
1526static void RDMFC1(void)
1527{
1528 dst->ops = current_instruction_table.DMFC1;
1529 recomp_func = gendmfc1;
1530 recompile_standard_r_type();
1531 dst->f.r.nrd = (src >> 11) & 0x1F;
1532 if (dst->f.r.rt == reg) RNOP();
1533}
1534
1535static void RCFC1(void)
1536{
1537 dst->ops = current_instruction_table.CFC1;
1538 recomp_func = gencfc1;
1539 recompile_standard_r_type();
1540 dst->f.r.nrd = (src >> 11) & 0x1F;
1541 if (dst->f.r.rt == reg) RNOP();
1542}
1543
1544static void RMTC1(void)
1545{
1546 dst->ops = current_instruction_table.MTC1;
1547 recompile_standard_r_type();
1548 recomp_func = genmtc1;
1549 dst->f.r.nrd = (src >> 11) & 0x1F;
1550}
1551
1552static void RDMTC1(void)
1553{
1554 dst->ops = current_instruction_table.DMTC1;
1555 recompile_standard_r_type();
1556 recomp_func = gendmtc1;
1557 dst->f.r.nrd = (src >> 11) & 0x1F;
1558}
1559
1560static void RCTC1(void)
1561{
1562 dst->ops = current_instruction_table.CTC1;
1563 recompile_standard_r_type();
1564 recomp_func = genctc1;
1565 dst->f.r.nrd = (src >> 11) & 0x1F;
1566}
1567
1568static void RBC(void)
1569{
1570 recomp_bc[((src >> 16) & 3)]();
1571}
1572
1573static void RS(void)
1574{
1575 recomp_s[(src & 0x3F)]();
1576}
1577
1578static void RD(void)
1579{
1580 recomp_d[(src & 0x3F)]();
1581}
1582
1583static void RW(void)
1584{
1585 recomp_w[(src & 0x3F)]();
1586}
1587
1588static void RL(void)
1589{
1590 recomp_l[(src & 0x3F)]();
1591}
1592
1593static void (*recomp_cop1[32])(void) =
1594{
1595 RMFC1, RDMFC1, RCFC1, RSV, RMTC1, RDMTC1, RCTC1, RSV,
1596 RBC , RSV , RSV , RSV, RSV , RSV , RSV , RSV,
1597 RS , RD , RSV , RSV, RW , RL , RSV , RSV,
1598 RSV , RSV , RSV , RSV, RSV , RSV , RSV , RSV
1599};
1600
1601//-------------------------------------------------------------------------
1602// R4300
1603//-------------------------------------------------------------------------
1604
1605static void RSPECIAL(void)
1606{
1607 recomp_special[(src & 0x3F)]();
1608}
1609
1610static void RREGIMM(void)
1611{
1612 recomp_regimm[((src >> 16) & 0x1F)]();
1613}
1614
1615static void RJ(void)
1616{
1617 unsigned int target;
1618 dst->ops = current_instruction_table.J;
1619 recomp_func = genj;
1620 recompile_standard_j_type();
1621 target = (dst->f.j.inst_index<<2) | (dst->addr & 0xF0000000);
1622 if (target == dst->addr)
1623 {
1624 if (check_nop)
1625 {
1626 dst->ops = current_instruction_table.J_IDLE;
1627 recomp_func = genj_idle;
1628 }
1629 }
1630 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1631 {
1632 dst->ops = current_instruction_table.J_OUT;
1633 recomp_func = genj_out;
1634 }
1635}
1636
1637static void RJAL(void)
1638{
1639 unsigned int target;
1640 dst->ops = current_instruction_table.JAL;
1641 recomp_func = genjal;
1642 recompile_standard_j_type();
1643 target = (dst->f.j.inst_index<<2) | (dst->addr & 0xF0000000);
1644 if (target == dst->addr)
1645 {
1646 if (check_nop)
1647 {
1648 dst->ops = current_instruction_table.JAL_IDLE;
1649 recomp_func = genjal_idle;
1650 }
1651 }
1652 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1653 {
1654 dst->ops = current_instruction_table.JAL_OUT;
1655 recomp_func = genjal_out;
1656 }
1657}
1658
1659static void RBEQ(void)
1660{
1661 unsigned int target;
1662 dst->ops = current_instruction_table.BEQ;
1663 recomp_func = genbeq;
1664 recompile_standard_i_type();
1665 target = dst->addr + dst->f.i.immediate*4 + 4;
1666 if (target == dst->addr)
1667 {
1668 if (check_nop)
1669 {
1670 dst->ops = current_instruction_table.BEQ_IDLE;
1671 recomp_func = genbeq_idle;
1672 }
1673 }
1674 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1675 {
1676 dst->ops = current_instruction_table.BEQ_OUT;
1677 recomp_func = genbeq_out;
1678 }
1679}
1680
1681static void RBNE(void)
1682{
1683 unsigned int target;
1684 dst->ops = current_instruction_table.BNE;
1685 recomp_func = genbne;
1686 recompile_standard_i_type();
1687 target = dst->addr + dst->f.i.immediate*4 + 4;
1688 if (target == dst->addr)
1689 {
1690 if (check_nop)
1691 {
1692 dst->ops = current_instruction_table.BNE_IDLE;
1693 recomp_func = genbne_idle;
1694 }
1695 }
1696 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1697 {
1698 dst->ops = current_instruction_table.BNE_OUT;
1699 recomp_func = genbne_out;
1700 }
1701}
1702
1703static void RBLEZ(void)
1704{
1705 unsigned int target;
1706 dst->ops = current_instruction_table.BLEZ;
1707 recomp_func = genblez;
1708 recompile_standard_i_type();
1709 target = dst->addr + dst->f.i.immediate*4 + 4;
1710 if (target == dst->addr)
1711 {
1712 if (check_nop)
1713 {
1714 dst->ops = current_instruction_table.BLEZ_IDLE;
1715 recomp_func = genblez_idle;
1716 }
1717 }
1718 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1719 {
1720 dst->ops = current_instruction_table.BLEZ_OUT;
1721 recomp_func = genblez_out;
1722 }
1723}
1724
1725static void RBGTZ(void)
1726{
1727 unsigned int target;
1728 dst->ops = current_instruction_table.BGTZ;
1729 recomp_func = genbgtz;
1730 recompile_standard_i_type();
1731 target = dst->addr + dst->f.i.immediate*4 + 4;
1732 if (target == dst->addr)
1733 {
1734 if (check_nop)
1735 {
1736 dst->ops = current_instruction_table.BGTZ_IDLE;
1737 recomp_func = genbgtz_idle;
1738 }
1739 }
1740 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1741 {
1742 dst->ops = current_instruction_table.BGTZ_OUT;
1743 recomp_func = genbgtz_out;
1744 }
1745}
1746
1747static void RADDI(void)
1748{
1749 dst->ops = current_instruction_table.ADDI;
1750 recomp_func = genaddi;
1751 recompile_standard_i_type();
1752 if(dst->f.i.rt == reg) RNOP();
1753}
1754
1755static void RADDIU(void)
1756{
1757 dst->ops = current_instruction_table.ADDIU;
1758 recomp_func = genaddiu;
1759 recompile_standard_i_type();
1760 if(dst->f.i.rt == reg) RNOP();
1761}
1762
1763static void RSLTI(void)
1764{
1765 dst->ops = current_instruction_table.SLTI;
1766 recomp_func = genslti;
1767 recompile_standard_i_type();
1768 if(dst->f.i.rt == reg) RNOP();
1769}
1770
1771static void RSLTIU(void)
1772{
1773 dst->ops = current_instruction_table.SLTIU;
1774 recomp_func = gensltiu;
1775 recompile_standard_i_type();
1776 if(dst->f.i.rt == reg) RNOP();
1777}
1778
1779static void RANDI(void)
1780{
1781 dst->ops = current_instruction_table.ANDI;
1782 recomp_func = genandi;
1783 recompile_standard_i_type();
1784 if(dst->f.i.rt == reg) RNOP();
1785}
1786
1787static void RORI(void)
1788{
1789 dst->ops = current_instruction_table.ORI;
1790 recomp_func = genori;
1791 recompile_standard_i_type();
1792 if (dst->f.i.rt == reg) RNOP();
1793}
1794
1795static void RXORI(void)
1796{
1797 dst->ops = current_instruction_table.XORI;
1798 recomp_func = genxori;
1799 recompile_standard_i_type();
1800 if (dst->f.i.rt == reg) RNOP();
1801}
1802
1803static void RLUI(void)
1804{
1805 dst->ops = current_instruction_table.LUI;
1806 recomp_func = genlui;
1807 recompile_standard_i_type();
1808 if (dst->f.i.rt == reg) RNOP();
1809}
1810
1811static void RCOP0(void)
1812{
1813 recomp_cop0[((src >> 21) & 0x1F)]();
1814}
1815
1816static void RCOP1(void)
1817{
1818 recomp_cop1[((src >> 21) & 0x1F)]();
1819}
1820
1821static void RBEQL(void)
1822{
1823 unsigned int target;
1824 dst->ops = current_instruction_table.BEQL;
1825 recomp_func = genbeql;
1826 recompile_standard_i_type();
1827 target = dst->addr + dst->f.i.immediate*4 + 4;
1828 if (target == dst->addr)
1829 {
1830 if (check_nop)
1831 {
1832 dst->ops = current_instruction_table.BEQL_IDLE;
1833 recomp_func = genbeql_idle;
1834 }
1835 }
1836 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1837 {
1838 dst->ops = current_instruction_table.BEQL_OUT;
1839 recomp_func = genbeql_out;
1840 }
1841}
1842
1843static void RBNEL(void)
1844{
1845 unsigned int target;
1846 dst->ops = current_instruction_table.BNEL;
1847 recomp_func = genbnel;
1848 recompile_standard_i_type();
1849 target = dst->addr + dst->f.i.immediate*4 + 4;
1850 if (target == dst->addr)
1851 {
1852 if (check_nop)
1853 {
1854 dst->ops = current_instruction_table.BNEL_IDLE;
1855 recomp_func = genbnel_idle;
1856 }
1857 }
1858 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1859 {
1860 dst->ops = current_instruction_table.BNEL_OUT;
1861 recomp_func = genbnel_out;
1862 }
1863}
1864
1865static void RBLEZL(void)
1866{
1867 unsigned int target;
1868 dst->ops = current_instruction_table.BLEZL;
1869 recomp_func = genblezl;
1870 recompile_standard_i_type();
1871 target = dst->addr + dst->f.i.immediate*4 + 4;
1872 if (target == dst->addr)
1873 {
1874 if (check_nop)
1875 {
1876 dst->ops = current_instruction_table.BLEZL_IDLE;
1877 recomp_func = genblezl_idle;
1878 }
1879 }
1880 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1881 {
1882 dst->ops = current_instruction_table.BLEZL_OUT;
1883 recomp_func = genblezl_out;
1884 }
1885}
1886
1887static void RBGTZL(void)
1888{
1889 unsigned int target;
1890 dst->ops = current_instruction_table.BGTZL;
1891 recomp_func = genbgtzl;
1892 recompile_standard_i_type();
1893 target = dst->addr + dst->f.i.immediate*4 + 4;
1894 if (target == dst->addr)
1895 {
1896 if (check_nop)
1897 {
1898 dst->ops = current_instruction_table.BGTZL_IDLE;
1899 recomp_func = genbgtzl_idle;
1900 }
1901 }
1902 else if (r4300emu != CORE_PURE_INTERPRETER && (target < dst_block->start || target >= dst_block->end || dst->addr == (dst_block->end-4)))
1903 {
1904 dst->ops = current_instruction_table.BGTZL_OUT;
1905 recomp_func = genbgtzl_out;
1906 }
1907}
1908
1909static void RDADDI(void)
1910{
1911 dst->ops = current_instruction_table.DADDI;
1912 recomp_func = gendaddi;
1913 recompile_standard_i_type();
1914 if(dst->f.i.rt == reg) RNOP();
1915}
1916
1917static void RDADDIU(void)
1918{
1919 dst->ops = current_instruction_table.DADDIU;
1920 recomp_func = gendaddiu;
1921 recompile_standard_i_type();
1922 if(dst->f.i.rt == reg) RNOP();
1923}
1924
1925static void RLDL(void)
1926{
1927 dst->ops = current_instruction_table.LDL;
1928 recomp_func = genldl;
1929 recompile_standard_i_type();
1930 if(dst->f.i.rt == reg) RNOP();
1931}
1932
1933static void RLDR(void)
1934{
1935 dst->ops = current_instruction_table.LDR;
1936 recomp_func = genldr;
1937 recompile_standard_i_type();
1938 if(dst->f.i.rt == reg) RNOP();
1939}
1940
1941static void RLB(void)
1942{
1943 dst->ops = current_instruction_table.LB;
1944 recomp_func = genlb;
1945 recompile_standard_i_type();
1946 if (dst->f.i.rt == reg) RNOP();
1947}
1948
1949static void RLH(void)
1950{
1951 dst->ops = current_instruction_table.LH;
1952 recomp_func = genlh;
1953 recompile_standard_i_type();
1954 if (dst->f.i.rt == reg) RNOP();
1955}
1956
1957static void RLWL(void)
1958{
1959 dst->ops = current_instruction_table.LWL;
1960 recomp_func = genlwl;
1961 recompile_standard_i_type();
1962 if (dst->f.i.rt == reg) RNOP();
1963}
1964
1965static void RLW(void)
1966{
1967 dst->ops = current_instruction_table.LW;
1968 recomp_func = genlw;
1969 recompile_standard_i_type();
1970 if (dst->f.i.rt == reg) RNOP();
1971}
1972
1973static void RLBU(void)
1974{
1975 dst->ops = current_instruction_table.LBU;
1976 recomp_func = genlbu;
1977 recompile_standard_i_type();
1978 if(dst->f.i.rt == reg) RNOP();
1979}
1980
1981static void RLHU(void)
1982{
1983 dst->ops = current_instruction_table.LHU;
1984 recomp_func = genlhu;
1985 recompile_standard_i_type();
1986 if(dst->f.i.rt == reg) RNOP();
1987}
1988
1989static void RLWR(void)
1990{
1991 dst->ops = current_instruction_table.LWR;
1992 recomp_func = genlwr;
1993 recompile_standard_i_type();
1994 if(dst->f.i.rt == reg) RNOP();
1995}
1996
1997static void RLWU(void)
1998{
1999 dst->ops = current_instruction_table.LWU;
2000 recomp_func = genlwu;
2001 recompile_standard_i_type();
2002 if(dst->f.i.rt == reg) RNOP();
2003}
2004
2005static void RSB(void)
2006{
2007 dst->ops = current_instruction_table.SB;
2008 recomp_func = gensb;
2009 recompile_standard_i_type();
2010}
2011
2012static void RSH(void)
2013{
2014 dst->ops = current_instruction_table.SH;
2015 recomp_func = gensh;
2016 recompile_standard_i_type();
2017}
2018
2019static void RSWL(void)
2020{
2021 dst->ops = current_instruction_table.SWL;
2022 recomp_func = genswl;
2023 recompile_standard_i_type();
2024}
2025
2026static void RSW(void)
2027{
2028 dst->ops = current_instruction_table.SW;
2029 recomp_func = gensw;
2030 recompile_standard_i_type();
2031}
2032
2033static void RSDL(void)
2034{
2035 dst->ops = current_instruction_table.SDL;
2036 recomp_func = gensdl;
2037 recompile_standard_i_type();
2038}
2039
2040static void RSDR(void)
2041{
2042 dst->ops = current_instruction_table.SDR;
2043 recomp_func = gensdr;
2044 recompile_standard_i_type();
2045}
2046
2047static void RSWR(void)
2048{
2049 dst->ops = current_instruction_table.SWR;
2050 recomp_func = genswr;
2051 recompile_standard_i_type();
2052}
2053
2054static void RCACHE(void)
2055{
2056 recomp_func = gencache;
2057 dst->ops = current_instruction_table.CACHE;
2058}
2059
2060static void RLL(void)
2061{
2062 recomp_func = genll;
2063 dst->ops = current_instruction_table.LL;
2064 recompile_standard_i_type();
2065 if(dst->f.i.rt == reg) RNOP();
2066}
2067
2068static void RLWC1(void)
2069{
2070 dst->ops = current_instruction_table.LWC1;
2071 recomp_func = genlwc1;
2072 recompile_standard_lf_type();
2073}
2074
2075static void RLLD(void)
2076{
2077 dst->ops = current_instruction_table.NI;
2078 recomp_func = genni;
2079 recompile_standard_i_type();
2080}
2081
2082static void RLDC1(void)
2083{
2084 dst->ops = current_instruction_table.LDC1;
2085 recomp_func = genldc1;
2086 recompile_standard_lf_type();
2087}
2088
2089static void RLD(void)
2090{
2091 dst->ops = current_instruction_table.LD;
2092 recomp_func = genld;
2093 recompile_standard_i_type();
2094 if (dst->f.i.rt == reg) RNOP();
2095}
2096
2097static void RSC(void)
2098{
2099 dst->ops = current_instruction_table.SC;
2100 recomp_func = gensc;
2101 recompile_standard_i_type();
2102 if (dst->f.i.rt == reg) RNOP();
2103}
2104
2105static void RSWC1(void)
2106{
2107 dst->ops = current_instruction_table.SWC1;
2108 recomp_func = genswc1;
2109 recompile_standard_lf_type();
2110}
2111
2112static void RSCD(void)
2113{
2114 dst->ops = current_instruction_table.NI;
2115 recomp_func = genni;
2116 recompile_standard_i_type();
2117}
2118
2119static void RSDC1(void)
2120{
2121 dst->ops = current_instruction_table.SDC1;
2122 recomp_func = gensdc1;
2123 recompile_standard_lf_type();
2124}
2125
2126static void RSD(void)
2127{
2128 dst->ops = current_instruction_table.SD;
2129 recomp_func = gensd;
2130 recompile_standard_i_type();
2131}
2132
2133static void (*recomp_ops[64])(void) =
2134{
2135 RSPECIAL, RREGIMM, RJ , RJAL , RBEQ , RBNE , RBLEZ , RBGTZ ,
2136 RADDI , RADDIU , RSLTI, RSLTIU, RANDI, RORI , RXORI , RLUI ,
2137 RCOP0 , RCOP1 , RSV , RSV , RBEQL, RBNEL, RBLEZL, RBGTZL,
2138 RDADDI , RDADDIU, RLDL , RLDR , RSV , RSV , RSV , RSV ,
2139 RLB , RLH , RLWL , RLW , RLBU , RLHU , RLWR , RLWU ,
2140 RSB , RSH , RSWL , RSW , RSDL , RSDR , RSWR , RCACHE,
2141 RLL , RLWC1 , RSV , RSV , RLLD , RLDC1, RSV , RLD ,
2142 RSC , RSWC1 , RSV , RSV , RSCD , RSDC1, RSV , RSD
2143};
2144
2145static int get_block_length(const precomp_block *block)
2146{
2147 return (block->end-block->start)/4;
2148}
2149
2150static size_t get_block_memsize(const precomp_block *block)
2151{
2152 int length = get_block_length(block);
2153 return ((length+1)+(length>>2)) * sizeof(precomp_instr);
2154}
2155
2156/**********************************************************************
2157 ******************** initialize an empty block ***********************
2158 **********************************************************************/
2159void init_block(precomp_block *block)
2160{
2161 int i, length, already_exist = 1;
2162 static int init_length;
2163 start_section(COMPILER_SECTION);
2164#ifdef CORE_DBG
2165 DebugMessage(M64MSG_INFO, "init block %x - %x", (int) block->start, (int) block->end);
2166#endif
2167
2168 length = get_block_length(block);
2169
2170 if (!block->block)
2171 {
2172 size_t memsize = get_block_memsize(block);
2173 if (r4300emu == CORE_DYNAREC) {
2174 block->block = (precomp_instr *) malloc_exec(memsize);
2175 if (!block->block) {
2176 DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate executable memory for dynamic recompiler. Try to use an interpreter mode.");
2177 return;
2178 }
2179 }
2180 else {
2181 block->block = (precomp_instr *) malloc(memsize);
2182 if (!block->block) {
2183 DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate memory for cached interpreter.");
2184 return;
2185 }
2186 }
2187
2188 memset(block->block, 0, memsize);
2189 already_exist = 0;
2190 }
2191
2192 if (r4300emu == CORE_DYNAREC)
2193 {
2194 if (!block->code)
2195 {
2196#if defined(PROFILE_R4300)
2197 max_code_length = 524288; /* allocate so much code space that we'll never have to realloc(), because this may */
2198 /* cause instruction locations to move, and break our profiling data */
2199#else
2200 max_code_length = 32768;
2201#endif
2202 block->code = (unsigned char *) malloc_exec(max_code_length);
2203 }
2204 else
2205 {
2206 max_code_length = block->max_code_length;
2207 }
2208 code_length = 0;
2209 inst_pointer = &block->code;
2210
2211 if (block->jumps_table)
2212 {
2213 free(block->jumps_table);
2214 block->jumps_table = NULL;
2215 }
2216 if (block->riprel_table)
2217 {
2218 free(block->riprel_table);
2219 block->riprel_table = NULL;
2220 }
2221 init_assembler(NULL, 0, NULL, 0);
2222 init_cache(block->block);
2223 }
2224
2225 if (!already_exist)
2226 {
2227#if defined(PROFILE_R4300)
2228 pfProfile = fopen("instructionaddrs.dat", "ab");
2229 long x86addr = (long) block->code;
2230 int mipsop = -2; /* -2 == NOTCOMPILED block at beginning of x86 code */
2231 if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode
2232 fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction
2233 DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
2234#endif
2235
2236 for (i=0; i<length; i++)
2237 {
2238 dst = block->block + i;
2239 dst->addr = block->start + i*4;
2240 dst->reg_cache_infos.need_map = 0;
2241 dst->local_addr = code_length;
2242#ifdef COMPARE_CORE
2243 if (r4300emu == CORE_DYNAREC) gendebug();
2244#endif
2245 RNOTCOMPILED();
2246 if (r4300emu == CORE_DYNAREC) recomp_func();
2247 }
2248#if defined(PROFILE_R4300)
2249 fclose(pfProfile);
2250 pfProfile = NULL;
2251#endif
2252 init_length = code_length;
2253 }
2254 else
2255 {
2256#if defined(PROFILE_R4300)
2257 code_length = block->code_length; /* leave old instructions in their place */
2258#else
2259 code_length = init_length; /* recompile everything, overwrite old recompiled instructions */
2260#endif
2261 for (i=0; i<length; i++)
2262 {
2263 dst = block->block + i;
2264 dst->reg_cache_infos.need_map = 0;
2265 dst->local_addr = i * (init_length / length);
2266 dst->ops = current_instruction_table.NOTCOMPILED;
2267 }
2268 }
2269
2270 if (r4300emu == CORE_DYNAREC)
2271 {
2272 free_all_registers();
2273 /* calling pass2 of the assembler is not necessary here because all of the code emitted by
2274 gennotcompiled() and gendebug() is position-independent and contains no jumps . */
2275 block->code_length = code_length;
2276 block->max_code_length = max_code_length;
2277 free_assembler(&block->jumps_table, &block->jumps_number, &block->riprel_table, &block->riprel_number);
2278 }
2279
2280 /* here we're marking the block as a valid code even if it's not compiled
2281 * yet as the game should have already set up the code correctly.
2282 */
2283 invalid_code[block->start>>12] = 0;
2284 if (block->end < 0x80000000 || block->start >= 0xc0000000)
2285 {
2286 unsigned int paddr;
2287
2288 paddr = virtual_to_physical_address(block->start, 2);
2289 invalid_code[paddr>>12] = 0;
2290 if (!blocks[paddr>>12])
2291 {
2292 blocks[paddr>>12] = (precomp_block *) malloc(sizeof(precomp_block));
2293 blocks[paddr>>12]->code = NULL;
2294 blocks[paddr>>12]->block = NULL;
2295 blocks[paddr>>12]->jumps_table = NULL;
2296 blocks[paddr>>12]->riprel_table = NULL;
2297 blocks[paddr>>12]->start = paddr & ~0xFFF;
2298 blocks[paddr>>12]->end = (paddr & ~0xFFF) + 0x1000;
2299 }
2300 init_block(blocks[paddr>>12]);
2301
2302 paddr += block->end - block->start - 4;
2303 invalid_code[paddr>>12] = 0;
2304 if (!blocks[paddr>>12])
2305 {
2306 blocks[paddr>>12] = (precomp_block *) malloc(sizeof(precomp_block));
2307 blocks[paddr>>12]->code = NULL;
2308 blocks[paddr>>12]->block = NULL;
2309 blocks[paddr>>12]->jumps_table = NULL;
2310 blocks[paddr>>12]->riprel_table = NULL;
2311 blocks[paddr>>12]->start = paddr & ~0xFFF;
2312 blocks[paddr>>12]->end = (paddr & ~0xFFF) + 0x1000;
2313 }
2314 init_block(blocks[paddr>>12]);
2315 }
2316 else
2317 {
2318 if (block->start >= 0x80000000 && block->end < 0xa0000000 && invalid_code[(block->start+0x20000000)>>12])
2319 {
2320 if (!blocks[(block->start+0x20000000)>>12])
2321 {
2322 blocks[(block->start+0x20000000)>>12] = (precomp_block *) malloc(sizeof(precomp_block));
2323 blocks[(block->start+0x20000000)>>12]->code = NULL;
2324 blocks[(block->start+0x20000000)>>12]->block = NULL;
2325 blocks[(block->start+0x20000000)>>12]->jumps_table = NULL;
2326 blocks[(block->start+0x20000000)>>12]->riprel_table = NULL;
2327 blocks[(block->start+0x20000000)>>12]->start = (block->start+0x20000000) & ~0xFFF;
2328 blocks[(block->start+0x20000000)>>12]->end = ((block->start+0x20000000) & ~0xFFF) + 0x1000;
2329 }
2330 init_block(blocks[(block->start+0x20000000)>>12]);
2331 }
2332 if (block->start >= 0xa0000000 && block->end < 0xc0000000 && invalid_code[(block->start-0x20000000)>>12])
2333 {
2334 if (!blocks[(block->start-0x20000000)>>12])
2335 {
2336 blocks[(block->start-0x20000000)>>12] = (precomp_block *) malloc(sizeof(precomp_block));
2337 blocks[(block->start-0x20000000)>>12]->code = NULL;
2338 blocks[(block->start-0x20000000)>>12]->block = NULL;
2339 blocks[(block->start-0x20000000)>>12]->jumps_table = NULL;
2340 blocks[(block->start-0x20000000)>>12]->riprel_table = NULL;
2341 blocks[(block->start-0x20000000)>>12]->start = (block->start-0x20000000) & ~0xFFF;
2342 blocks[(block->start-0x20000000)>>12]->end = ((block->start-0x20000000) & ~0xFFF) + 0x1000;
2343 }
2344 init_block(blocks[(block->start-0x20000000)>>12]);
2345 }
2346 }
2347 end_section(COMPILER_SECTION);
2348}
2349
2350void free_block(precomp_block *block)
2351{
2352 size_t memsize = get_block_memsize(block);
2353
2354 if (block->block) {
2355 if (r4300emu == CORE_DYNAREC)
2356 free_exec(block->block, memsize);
2357 else
2358 free(block->block);
2359 block->block = NULL;
2360 }
2361 if (block->code) { free_exec(block->code, block->max_code_length); block->code = NULL; }
2362 if (block->jumps_table) { free(block->jumps_table); block->jumps_table = NULL; }
2363 if (block->riprel_table) { free(block->riprel_table); block->riprel_table = NULL; }
2364}
2365
2366/**********************************************************************
2367 ********************* recompile a block of code **********************
2368 **********************************************************************/
2369void recompile_block(int *source, precomp_block *block, unsigned int func)
2370{
2371 int i, length, finished=0;
2372 start_section(COMPILER_SECTION);
2373 length = (block->end-block->start)/4;
2374 dst_block = block;
2375
2376 //for (i=0; i<16; i++) block->md5[i] = 0;
2377 block->adler32 = 0;
2378
2379 if (r4300emu == CORE_DYNAREC)
2380 {
2381 code_length = block->code_length;
2382 max_code_length = block->max_code_length;
2383 inst_pointer = &block->code;
2384 init_assembler(block->jumps_table, block->jumps_number, block->riprel_table, block->riprel_number);
2385 init_cache(block->block + (func & 0xFFF) / 4);
2386 }
2387
2388#if defined(PROFILE_R4300)
2389 pfProfile = fopen("instructionaddrs.dat", "ab");
2390#endif
2391
2392 for (i = (func & 0xFFF) / 4; finished != 2; i++)
2393 {
2394 if(block->start < 0x80000000 || block->start >= 0xc0000000)
2395 {
2396 unsigned int address2 =
2397 virtual_to_physical_address(block->start + i*4, 0);
2398 if(blocks[address2>>12]->block[(address2&0xFFF)/4].ops == current_instruction_table.NOTCOMPILED)
2399 blocks[address2>>12]->block[(address2&0xFFF)/4].ops = current_instruction_table.NOTCOMPILED2;
2400 }
2401
2402 SRC = source + i;
2403 src = source[i];
2404 check_nop = source[i+1] == 0;
2405 dst = block->block + i;
2406 dst->addr = block->start + i*4;
2407 dst->reg_cache_infos.need_map = 0;
2408 dst->local_addr = code_length;
2409#ifdef COMPARE_CORE
2410 if (r4300emu == CORE_DYNAREC) gendebug();
2411#endif
2412#if defined(PROFILE_R4300)
2413 long x86addr = (long) (block->code + block->block[i].local_addr);
2414 if (fwrite(source + i, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode
2415 fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction
2416 DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
2417#endif
2418 recomp_func = NULL;
2419 recomp_ops[((src >> 26) & 0x3F)]();
2420 if (r4300emu == CORE_DYNAREC) recomp_func();
2421 dst = block->block + i;
2422
2423 /*if ((dst+1)->ops != NOTCOMPILED && !delay_slot_compiled &&
2424 i < length)
2425 {
2426 if (r4300emu == CORE_DYNAREC) genlink_subblock();
2427 finished = 2;
2428 }*/
2429 if (delay_slot_compiled)
2430 {
2431 delay_slot_compiled--;
2432 free_all_registers();
2433 }
2434
2435 if (i >= length-2+(length>>2)) finished = 2;
2436 if (i >= (length-1) && (block->start == 0xa4000000 ||
2437 block->start >= 0xc0000000 ||
2438 block->end < 0x80000000)) finished = 2;
2439 if (dst->ops == current_instruction_table.ERET || finished == 1) finished = 2;
2440 if (/*i >= length &&*/
2441 (dst->ops == current_instruction_table.J ||
2442 dst->ops == current_instruction_table.J_OUT ||
2443 dst->ops == current_instruction_table.JR) &&
2444 !(i >= (length-1) && (block->start >= 0xc0000000 ||
2445 block->end < 0x80000000)))
2446 finished = 1;
2447 }
2448
2449#if defined(PROFILE_R4300)
2450 long x86addr = (long) (block->code + code_length);
2451 int mipsop = -3; /* -3 == block-postfix */
2452 if (fwrite(&mipsop, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode
2453 fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction
2454 DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
2455#endif
2456
2457 if (i >= length)
2458 {
2459 dst = block->block + i;
2460 dst->addr = block->start + i*4;
2461 dst->reg_cache_infos.need_map = 0;
2462 dst->local_addr = code_length;
2463#ifdef COMPARE_CORE
2464 if (r4300emu == CORE_DYNAREC) gendebug();
2465#endif
2466 RFIN_BLOCK();
2467 if (r4300emu == CORE_DYNAREC) recomp_func();
2468 i++;
2469 if (i < length-1+(length>>2)) // useful when last opcode is a jump
2470 {
2471 dst = block->block + i;
2472 dst->addr = block->start + i*4;
2473 dst->reg_cache_infos.need_map = 0;
2474 dst->local_addr = code_length;
2475#ifdef COMPARE_CORE
2476 if (r4300emu == CORE_DYNAREC) gendebug();
2477#endif
2478 RFIN_BLOCK();
2479 if (r4300emu == CORE_DYNAREC) recomp_func();
2480 i++;
2481 }
2482 }
2483 else if (r4300emu == CORE_DYNAREC) genlink_subblock();
2484
2485 if (r4300emu == CORE_DYNAREC)
2486 {
2487 free_all_registers();
2488 passe2(block->block, (func&0xFFF)/4, i, block);
2489 block->code_length = code_length;
2490 block->max_code_length = max_code_length;
2491 free_assembler(&block->jumps_table, &block->jumps_number, &block->riprel_table, &block->riprel_number);
2492 }
2493#ifdef CORE_DBG
2494 DebugMessage(M64MSG_INFO, "block recompiled (%x-%x)", (int)func, (int)(block->start+i*4));
2495#endif
2496#if defined(PROFILE_R4300)
2497 fclose(pfProfile);
2498 pfProfile = NULL;
2499#endif
2500 end_section(COMPILER_SECTION);
2501}
2502
2503static int is_jump(void)
2504{
2505 recomp_ops[((src >> 26) & 0x3F)]();
2506 return
2507 (dst->ops == current_instruction_table.J ||
2508 dst->ops == current_instruction_table.J_OUT ||
2509 dst->ops == current_instruction_table.J_IDLE ||
2510 dst->ops == current_instruction_table.JAL ||
2511 dst->ops == current_instruction_table.JAL_OUT ||
2512 dst->ops == current_instruction_table.JAL_IDLE ||
2513 dst->ops == current_instruction_table.BEQ ||
2514 dst->ops == current_instruction_table.BEQ_OUT ||
2515 dst->ops == current_instruction_table.BEQ_IDLE ||
2516 dst->ops == current_instruction_table.BNE ||
2517 dst->ops == current_instruction_table.BNE_OUT ||
2518 dst->ops == current_instruction_table.BNE_IDLE ||
2519 dst->ops == current_instruction_table.BLEZ ||
2520 dst->ops == current_instruction_table.BLEZ_OUT ||
2521 dst->ops == current_instruction_table.BLEZ_IDLE ||
2522 dst->ops == current_instruction_table.BGTZ ||
2523 dst->ops == current_instruction_table.BGTZ_OUT ||
2524 dst->ops == current_instruction_table.BGTZ_IDLE ||
2525 dst->ops == current_instruction_table.BEQL ||
2526 dst->ops == current_instruction_table.BEQL_OUT ||
2527 dst->ops == current_instruction_table.BEQL_IDLE ||
2528 dst->ops == current_instruction_table.BNEL ||
2529 dst->ops == current_instruction_table.BNEL_OUT ||
2530 dst->ops == current_instruction_table.BNEL_IDLE ||
2531 dst->ops == current_instruction_table.BLEZL ||
2532 dst->ops == current_instruction_table.BLEZL_OUT ||
2533 dst->ops == current_instruction_table.BLEZL_IDLE ||
2534 dst->ops == current_instruction_table.BGTZL ||
2535 dst->ops == current_instruction_table.BGTZL_OUT ||
2536 dst->ops == current_instruction_table.BGTZL_IDLE ||
2537 dst->ops == current_instruction_table.JR ||
2538 dst->ops == current_instruction_table.JALR ||
2539 dst->ops == current_instruction_table.BLTZ ||
2540 dst->ops == current_instruction_table.BLTZ_OUT ||
2541 dst->ops == current_instruction_table.BLTZ_IDLE ||
2542 dst->ops == current_instruction_table.BGEZ ||
2543 dst->ops == current_instruction_table.BGEZ_OUT ||
2544 dst->ops == current_instruction_table.BGEZ_IDLE ||
2545 dst->ops == current_instruction_table.BLTZL ||
2546 dst->ops == current_instruction_table.BLTZL_OUT ||
2547 dst->ops == current_instruction_table.BLTZL_IDLE ||
2548 dst->ops == current_instruction_table.BGEZL ||
2549 dst->ops == current_instruction_table.BGEZL_OUT ||
2550 dst->ops == current_instruction_table.BGEZL_IDLE ||
2551 dst->ops == current_instruction_table.BLTZAL ||
2552 dst->ops == current_instruction_table.BLTZAL_OUT ||
2553 dst->ops == current_instruction_table.BLTZAL_IDLE ||
2554 dst->ops == current_instruction_table.BGEZAL ||
2555 dst->ops == current_instruction_table.BGEZAL_OUT ||
2556 dst->ops == current_instruction_table.BGEZAL_IDLE ||
2557 dst->ops == current_instruction_table.BLTZALL ||
2558 dst->ops == current_instruction_table.BLTZALL_OUT ||
2559 dst->ops == current_instruction_table.BLTZALL_IDLE ||
2560 dst->ops == current_instruction_table.BGEZALL ||
2561 dst->ops == current_instruction_table.BGEZALL_OUT ||
2562 dst->ops == current_instruction_table.BGEZALL_IDLE ||
2563 dst->ops == current_instruction_table.BC1F ||
2564 dst->ops == current_instruction_table.BC1F_OUT ||
2565 dst->ops == current_instruction_table.BC1F_IDLE ||
2566 dst->ops == current_instruction_table.BC1T ||
2567 dst->ops == current_instruction_table.BC1T_OUT ||
2568 dst->ops == current_instruction_table.BC1T_IDLE ||
2569 dst->ops == current_instruction_table.BC1FL ||
2570 dst->ops == current_instruction_table.BC1FL_OUT ||
2571 dst->ops == current_instruction_table.BC1FL_IDLE ||
2572 dst->ops == current_instruction_table.BC1TL ||
2573 dst->ops == current_instruction_table.BC1TL_OUT ||
2574 dst->ops == current_instruction_table.BC1TL_IDLE);
2575}
2576
2577/**********************************************************************
2578 ************ recompile only one opcode (use for delay slot) **********
2579 **********************************************************************/
2580void recompile_opcode(void)
2581{
2582 SRC++;
2583 src = *SRC;
2584 dst++;
2585 dst->addr = (dst-1)->addr + 4;
2586 dst->reg_cache_infos.need_map = 0;
2587 if(!is_jump())
2588 {
2589#if defined(PROFILE_R4300)
2590 long x86addr = (long) ((*inst_pointer) + code_length);
2591 if (fwrite(&src, 1, 4, pfProfile) != 4 || // write 4-byte MIPS opcode
2592 fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *)) // write pointer to dynamically generated x86 code for this MIPS instruction
2593 DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
2594#endif
2595 recomp_func = NULL;
2596 recomp_ops[((src >> 26) & 0x3F)]();
2597 if (r4300emu == CORE_DYNAREC) recomp_func();
2598 }
2599 else
2600 {
2601 RNOP();
2602 if (r4300emu == CORE_DYNAREC) recomp_func();
2603 }
2604 delay_slot_compiled = 2;
2605}
2606
2607/**********************************************************************
2608 ************** decode one opcode (for the interpreter) ***************
2609 **********************************************************************/
2610void prefetch_opcode(unsigned int op, unsigned int nextop)
2611{
2612 dst = PC;
2613 src = op;
2614 check_nop = nextop == 0;
2615 recomp_ops[((src >> 26) & 0x3F)]();
2616}
2617
2618/**********************************************************************
2619 ************** allocate memory with executable bit set ***************
2620 **********************************************************************/
2621static void *malloc_exec(size_t size)
2622{
2623#if defined(WIN32)
2624 return VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
2625#elif defined(__GNUC__)
2626
2627 #ifndef MAP_ANONYMOUS
2628 #ifdef MAP_ANON
2629 #define MAP_ANONYMOUS MAP_ANON
2630 #endif
2631 #endif
2632
2633 void *block = mmap(NULL, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
2634 if (block == MAP_FAILED)
2635 { DebugMessage(M64MSG_ERROR, "Memory error: couldn't allocate %zi byte block of aligned RWX memory.", size); return NULL; }
2636
2637 return block;
2638#else
2639 return malloc(size);
2640#endif
2641}
2642
2643/**********************************************************************
2644 ************* reallocate memory with executable bit set **************
2645 **********************************************************************/
2646void *realloc_exec(void *ptr, size_t oldsize, size_t newsize)
2647{
2648 void* block = malloc_exec(newsize);
2649 if (block != NULL)
2650 {
2651 size_t copysize;
2652 if (oldsize < newsize)
2653 copysize = oldsize;
2654 else
2655 copysize = newsize;
2656 memcpy(block, ptr, copysize);
2657 }
2658 free_exec(ptr, oldsize);
2659 return block;
2660}
2661
2662/**********************************************************************
2663 **************** frees memory with executable bit set ****************
2664 **********************************************************************/
2665static void free_exec(void *ptr, size_t length)
2666{
2667#if defined(WIN32)
2668 VirtualFree(ptr, 0, MEM_RELEASE);
2669#elif defined(__GNUC__)
2670 munmap(ptr, length);
2671#else
2672 free(ptr);
2673#endif
2674}