Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-core/src/r4300/recomp.c
2 views
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
42
static void *malloc_exec(size_t size);
43
static void free_exec(void *ptr, size_t length);
44
45
// global variables :
46
precomp_instr *dst; // destination structure for the recompiled instruction
47
int code_length; // current real recompiled code length
48
int max_code_length; // current recompiled code's buffer length
49
unsigned char **inst_pointer; // output buffer for recompiled code
50
precomp_block *dst_block; // the current block that we are recompiling
51
int src; // the current recompiled instruction
52
int fast_memory;
53
54
static void (*recomp_func)(void); // pointer to the dynarec's generator
55
// function for the latest decoded opcode
56
57
#if defined(PROFILE_R4300)
58
FILE *pfProfile;
59
#endif
60
61
static int *SRC; // currently recompiled instruction in the input stream
62
static int check_nop; // next instruction is nop ?
63
static int delay_slot_compiled = 0;
64
65
66
67
static void RSV(void)
68
{
69
dst->ops = current_instruction_table.RESERVED;
70
recomp_func = genreserved;
71
}
72
73
static void RFIN_BLOCK(void)
74
{
75
dst->ops = current_instruction_table.FIN_BLOCK;
76
recomp_func = genfin_block;
77
}
78
79
static void RNOTCOMPILED(void)
80
{
81
dst->ops = current_instruction_table.NOTCOMPILED;
82
recomp_func = gennotcompiled;
83
}
84
85
static 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
92
static void recompile_standard_j_type(void)
93
{
94
dst->f.j.inst_index = src & 0x3FFFFFF;
95
}
96
97
static 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
105
static 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
112
static 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
123
static void RNOP(void)
124
{
125
dst->ops = current_instruction_table.NOP;
126
recomp_func = gennop;
127
}
128
129
static 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
137
static 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
145
static 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
153
static 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
161
static 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
169
static 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
177
static void RJR(void)
178
{
179
dst->ops = current_instruction_table.JR;
180
recomp_func = genjr;
181
recompile_standard_i_type();
182
}
183
184
static void RJALR(void)
185
{
186
dst->ops = current_instruction_table.JALR;
187
recomp_func = genjalr;
188
recompile_standard_r_type();
189
}
190
191
static void RSYSCALL(void)
192
{
193
dst->ops = current_instruction_table.SYSCALL;
194
recomp_func = gensyscall;
195
}
196
197
static void RBREAK(void)
198
{
199
dst->ops = current_instruction_table.NI;
200
recomp_func = genni;
201
}
202
203
static void RSYNC(void)
204
{
205
dst->ops = current_instruction_table.SYNC;
206
recomp_func = gensync;
207
}
208
209
static 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
217
static void RMTHI(void)
218
{
219
dst->ops = current_instruction_table.MTHI;
220
recomp_func = genmthi;
221
recompile_standard_r_type();
222
}
223
224
static 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
232
static void RMTLO(void)
233
{
234
dst->ops = current_instruction_table.MTLO;
235
recomp_func = genmtlo;
236
recompile_standard_r_type();
237
}
238
239
static 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
247
static 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
255
static 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
263
static void RMULT(void)
264
{
265
dst->ops = current_instruction_table.MULT;
266
recomp_func = genmult;
267
recompile_standard_r_type();
268
}
269
270
static void RMULTU(void)
271
{
272
dst->ops = current_instruction_table.MULTU;
273
recomp_func = genmultu;
274
recompile_standard_r_type();
275
}
276
277
static void RDIV(void)
278
{
279
dst->ops = current_instruction_table.DIV;
280
recomp_func = gendiv;
281
recompile_standard_r_type();
282
}
283
284
static void RDIVU(void)
285
{
286
dst->ops = current_instruction_table.DIVU;
287
recomp_func = gendivu;
288
recompile_standard_r_type();
289
}
290
291
static void RDMULT(void)
292
{
293
dst->ops = current_instruction_table.DMULT;
294
recomp_func = gendmult;
295
recompile_standard_r_type();
296
}
297
298
static void RDMULTU(void)
299
{
300
dst->ops = current_instruction_table.DMULTU;
301
recomp_func = gendmultu;
302
recompile_standard_r_type();
303
}
304
305
static void RDDIV(void)
306
{
307
dst->ops = current_instruction_table.DDIV;
308
recomp_func = genddiv;
309
recompile_standard_r_type();
310
}
311
312
static void RDDIVU(void)
313
{
314
dst->ops = current_instruction_table.DDIVU;
315
recomp_func = genddivu;
316
recompile_standard_r_type();
317
}
318
319
static 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
327
static 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
335
static 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
343
static 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
351
static 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
359
static 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
367
static 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
375
static 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
383
static 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
391
static 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
399
static 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
407
static 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
415
static 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
423
static 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
431
static void RTGE(void)
432
{
433
dst->ops = current_instruction_table.NI;
434
recomp_func = genni;
435
}
436
437
static void RTGEU(void)
438
{
439
dst->ops = current_instruction_table.NI;
440
recomp_func = genni;
441
}
442
443
static void RTLT(void)
444
{
445
dst->ops = current_instruction_table.NI;
446
recomp_func = genni;
447
}
448
449
static void RTLTU(void)
450
{
451
dst->ops = current_instruction_table.NI;
452
recomp_func = genni;
453
}
454
455
static void RTEQ(void)
456
{
457
dst->ops = current_instruction_table.TEQ;
458
recomp_func = genteq;
459
recompile_standard_r_type();
460
}
461
462
static void RTNE(void)
463
{
464
dst->ops = current_instruction_table.NI;
465
recomp_func = genni;
466
}
467
468
static 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
476
static 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
484
static 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
492
static 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
500
static 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
508
static 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
516
static 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
532
static 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
554
static 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
576
static 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
598
static 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
620
static void RTGEI(void)
621
{
622
dst->ops = current_instruction_table.NI;
623
recomp_func = genni;
624
}
625
626
static void RTGEIU(void)
627
{
628
dst->ops = current_instruction_table.NI;
629
recomp_func = genni;
630
}
631
632
static void RTLTI(void)
633
{
634
dst->ops = current_instruction_table.NI;
635
recomp_func = genni;
636
}
637
638
static void RTLTIU(void)
639
{
640
dst->ops = current_instruction_table.NI;
641
recomp_func = genni;
642
}
643
644
static void RTEQI(void)
645
{
646
dst->ops = current_instruction_table.NI;
647
recomp_func = genni;
648
}
649
650
static void RTNEI(void)
651
{
652
dst->ops = current_instruction_table.NI;
653
recomp_func = genni;
654
}
655
656
static 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
678
static 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
700
static 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
722
static 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
744
static 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
756
static void RTLBR(void)
757
{
758
dst->ops = current_instruction_table.TLBR;
759
recomp_func = gentlbr;
760
}
761
762
static void RTLBWI(void)
763
{
764
dst->ops = current_instruction_table.TLBWI;
765
recomp_func = gentlbwi;
766
}
767
768
static void RTLBWR(void)
769
{
770
dst->ops = current_instruction_table.TLBWR;
771
recomp_func = gentlbwr;
772
}
773
774
static void RTLBP(void)
775
{
776
dst->ops = current_instruction_table.TLBP;
777
recomp_func = gentlbp;
778
}
779
780
static void RERET(void)
781
{
782
dst->ops = current_instruction_table.ERET;
783
recomp_func = generet;
784
}
785
786
static 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
802
static 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
812
static 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
820
static void RTLB(void)
821
{
822
recomp_tlb[(src & 0x3F)]();
823
}
824
825
static 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
837
static 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
859
static 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
881
static 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
903
static 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
925
static void (*recomp_bc[4])(void) =
926
{
927
RBC1F , RBC1T ,
928
RBC1FL, RBC1TL
929
};
930
931
//-------------------------------------------------------------------------
932
// S
933
//-------------------------------------------------------------------------
934
935
static 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
942
static 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
949
static 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
956
static 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
963
static 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
970
static 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
977
static 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
984
static 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
991
static 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
998
static 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
1005
static 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
1012
static 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
1019
static 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
1026
static 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
1033
static 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
1040
static 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
1047
static 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
1054
static 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
1061
static 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
1068
static 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
1075
static 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
1082
static 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
1089
static 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
1096
static 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
1103
static 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
1110
static 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
1117
static 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
1124
static 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
1131
static 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
1138
static 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
1145
static 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
1152
static 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
1159
static 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
1166
static 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
1173
static 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
1180
static 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
1196
static 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
1203
static 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
1210
static 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
1217
static 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
1224
static 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
1231
static 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
1238
static 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
1245
static 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
1252
static 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
1259
static 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
1266
static 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
1273
static 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
1280
static 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
1287
static 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
1294
static 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
1301
static 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
1308
static 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
1315
static 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
1322
static 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
1329
static 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
1336
static 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
1343
static 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
1350
static 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
1357
static 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
1364
static 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
1371
static 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
1378
static 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
1385
static 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
1392
static 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
1399
static 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
1406
static 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
1413
static 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
1420
static 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
1427
static 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
1434
static 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
1441
static 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
1457
static 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
1464
static 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
1471
static 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
1487
static 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
1494
static 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
1501
static 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
1517
static 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
1526
static 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
1535
static 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
1544
static 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
1552
static 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
1560
static 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
1568
static void RBC(void)
1569
{
1570
recomp_bc[((src >> 16) & 3)]();
1571
}
1572
1573
static void RS(void)
1574
{
1575
recomp_s[(src & 0x3F)]();
1576
}
1577
1578
static void RD(void)
1579
{
1580
recomp_d[(src & 0x3F)]();
1581
}
1582
1583
static void RW(void)
1584
{
1585
recomp_w[(src & 0x3F)]();
1586
}
1587
1588
static void RL(void)
1589
{
1590
recomp_l[(src & 0x3F)]();
1591
}
1592
1593
static 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
1605
static void RSPECIAL(void)
1606
{
1607
recomp_special[(src & 0x3F)]();
1608
}
1609
1610
static void RREGIMM(void)
1611
{
1612
recomp_regimm[((src >> 16) & 0x1F)]();
1613
}
1614
1615
static 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
1637
static 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
1659
static 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
1681
static 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
1703
static 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
1725
static 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
1747
static 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
1755
static 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
1763
static 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
1771
static 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
1779
static 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
1787
static 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
1795
static 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
1803
static 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
1811
static void RCOP0(void)
1812
{
1813
recomp_cop0[((src >> 21) & 0x1F)]();
1814
}
1815
1816
static void RCOP1(void)
1817
{
1818
recomp_cop1[((src >> 21) & 0x1F)]();
1819
}
1820
1821
static 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
1843
static 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
1865
static 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
1887
static 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
1909
static 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
1917
static 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
1925
static 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
1933
static 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
1941
static 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
1949
static 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
1957
static 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
1965
static 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
1973
static 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
1981
static 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
1989
static 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
1997
static 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
2005
static void RSB(void)
2006
{
2007
dst->ops = current_instruction_table.SB;
2008
recomp_func = gensb;
2009
recompile_standard_i_type();
2010
}
2011
2012
static void RSH(void)
2013
{
2014
dst->ops = current_instruction_table.SH;
2015
recomp_func = gensh;
2016
recompile_standard_i_type();
2017
}
2018
2019
static void RSWL(void)
2020
{
2021
dst->ops = current_instruction_table.SWL;
2022
recomp_func = genswl;
2023
recompile_standard_i_type();
2024
}
2025
2026
static void RSW(void)
2027
{
2028
dst->ops = current_instruction_table.SW;
2029
recomp_func = gensw;
2030
recompile_standard_i_type();
2031
}
2032
2033
static void RSDL(void)
2034
{
2035
dst->ops = current_instruction_table.SDL;
2036
recomp_func = gensdl;
2037
recompile_standard_i_type();
2038
}
2039
2040
static void RSDR(void)
2041
{
2042
dst->ops = current_instruction_table.SDR;
2043
recomp_func = gensdr;
2044
recompile_standard_i_type();
2045
}
2046
2047
static void RSWR(void)
2048
{
2049
dst->ops = current_instruction_table.SWR;
2050
recomp_func = genswr;
2051
recompile_standard_i_type();
2052
}
2053
2054
static void RCACHE(void)
2055
{
2056
recomp_func = gencache;
2057
dst->ops = current_instruction_table.CACHE;
2058
}
2059
2060
static 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
2068
static void RLWC1(void)
2069
{
2070
dst->ops = current_instruction_table.LWC1;
2071
recomp_func = genlwc1;
2072
recompile_standard_lf_type();
2073
}
2074
2075
static void RLLD(void)
2076
{
2077
dst->ops = current_instruction_table.NI;
2078
recomp_func = genni;
2079
recompile_standard_i_type();
2080
}
2081
2082
static void RLDC1(void)
2083
{
2084
dst->ops = current_instruction_table.LDC1;
2085
recomp_func = genldc1;
2086
recompile_standard_lf_type();
2087
}
2088
2089
static 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
2097
static 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
2105
static void RSWC1(void)
2106
{
2107
dst->ops = current_instruction_table.SWC1;
2108
recomp_func = genswc1;
2109
recompile_standard_lf_type();
2110
}
2111
2112
static void RSCD(void)
2113
{
2114
dst->ops = current_instruction_table.NI;
2115
recomp_func = genni;
2116
recompile_standard_i_type();
2117
}
2118
2119
static void RSDC1(void)
2120
{
2121
dst->ops = current_instruction_table.SDC1;
2122
recomp_func = gensdc1;
2123
recompile_standard_lf_type();
2124
}
2125
2126
static void RSD(void)
2127
{
2128
dst->ops = current_instruction_table.SD;
2129
recomp_func = gensd;
2130
recompile_standard_i_type();
2131
}
2132
2133
static 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
2145
static int get_block_length(const precomp_block *block)
2146
{
2147
return (block->end-block->start)/4;
2148
}
2149
2150
static 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
**********************************************************************/
2159
void 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
2350
void 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
**********************************************************************/
2369
void 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
2503
static 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
**********************************************************************/
2580
void 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
**********************************************************************/
2610
void 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
**********************************************************************/
2621
static 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
**********************************************************************/
2646
void *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
**********************************************************************/
2665
static 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
}
2675
2676