Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/libmupen64plus/mupen64plus-core/src/r4300/r4300.c
2 views
1
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2
* Mupen64plus - r4300.c *
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
#include "api/m64p_types.h"
26
#include "api/callbacks.h"
27
#include "api/debugger.h"
28
#include "memory/memory.h"
29
#include "main/main.h"
30
#include "main/rom.h"
31
32
#include "r4300.h"
33
#include "ops.h"
34
#include "exception.h"
35
#include "interupt.h"
36
#include "macros.h"
37
#include "recomp.h"
38
#include "recomph.h"
39
#include "new_dynarec/new_dynarec.h"
40
41
#ifdef DBG
42
#include "debugger/dbg_types.h"
43
#include "debugger/debugger.h"
44
#endif
45
46
unsigned int r4300emu = 0;
47
int no_compiled_jump = 0;
48
int llbit; //, rompause;
49
HANDLE rompausesem;
50
#if NEW_DYNAREC != NEW_DYNAREC_ARM
51
int stop;
52
long long int reg[32], hi, lo;
53
unsigned int reg_cop0[32];
54
float *reg_cop1_simple[32];
55
double *reg_cop1_double[32];
56
int FCR0, FCR31;
57
unsigned int next_interupt;
58
precomp_instr *PC;
59
#endif
60
long long int local_rs;
61
long long int reg_cop1_fgr_64[32];
62
tlb tlb_e[32];
63
unsigned int delay_slot, skip_jump = 0, dyna_interp = 0, last_addr;
64
unsigned long long int debug_count = 0;
65
unsigned int CIC_Chip;
66
char invalid_code[0x100000];
67
68
precomp_block *blocks[0x100000], *actual;
69
int rounding_mode = 0x33F, trunc_mode = 0xF3F, round_mode = 0x33F,
70
ceil_mode = 0xB3F, floor_mode = 0x73F;
71
72
// -----------------------------------------------------------
73
// Cached interpreter functions (and fallback for dynarec).
74
// -----------------------------------------------------------
75
#ifdef DBG
76
#define UPDATE_DEBUGGER() if (g_DebuggerActive) update_debugger(PC->addr, -1)
77
#else
78
#define UPDATE_DEBUGGER() do { } while(0)
79
#endif
80
81
#define PCADDR PC->addr
82
#define ADD_TO_PC(x) PC += x;
83
#define DECLARE_INSTRUCTION(name) static void name(void)
84
85
#define DECLARE_JUMP(name, destination, condition, link, likely, cop1) \
86
static void name(void) \
87
{ \
88
const int take_jump = (condition); \
89
const unsigned int jump_target = (destination); \
90
long long int *link_register = (link); \
91
if (cop1 && check_cop1_unusable()) return; \
92
if (!likely || take_jump) \
93
{ \
94
PC++; \
95
delay_slot=1; \
96
UPDATE_DEBUGGER(); \
97
PC->ops(); \
98
update_count(); \
99
delay_slot=0; \
100
if (take_jump && !skip_jump) \
101
{ \
102
if (link_register != &reg[0]) \
103
{ \
104
*link_register=PC->addr; \
105
sign_extended(*link_register); \
106
} \
107
PC=actual->block+((jump_target-actual->start)>>2); \
108
} \
109
} \
110
else \
111
{ \
112
PC += 2; \
113
update_count(); \
114
} \
115
last_addr = PC->addr; \
116
if (next_interupt <= Count) gen_interupt(); \
117
} \
118
static void name##_OUT(void) \
119
{ \
120
const int take_jump = (condition); \
121
const unsigned int jump_target = (destination); \
122
long long int *link_register = (link); \
123
if (cop1 && check_cop1_unusable()) return; \
124
if (!likely || take_jump) \
125
{ \
126
PC++; \
127
delay_slot=1; \
128
UPDATE_DEBUGGER(); \
129
PC->ops(); \
130
update_count(); \
131
delay_slot=0; \
132
if (take_jump && !skip_jump) \
133
{ \
134
if (link_register != &reg[0]) \
135
{ \
136
*link_register=PC->addr; \
137
sign_extended(*link_register); \
138
} \
139
jump_to(jump_target); \
140
} \
141
} \
142
else \
143
{ \
144
PC += 2; \
145
update_count(); \
146
} \
147
last_addr = PC->addr; \
148
if (next_interupt <= Count) gen_interupt(); \
149
} \
150
static void name##_IDLE(void) \
151
{ \
152
const int take_jump = (condition); \
153
int skip; \
154
if (cop1 && check_cop1_unusable()) return; \
155
if (take_jump) \
156
{ \
157
update_count(); \
158
skip = next_interupt - Count; \
159
if (skip > 3) Count += (skip & 0xFFFFFFFC); \
160
else name(); \
161
} \
162
else name(); \
163
}
164
165
#define CHECK_MEMORY() \
166
if (!invalid_code[address>>12]) \
167
if (blocks[address>>12]->block[(address&0xFFF)/4].ops != \
168
current_instruction_table.NOTCOMPILED) \
169
invalid_code[address>>12] = 1;
170
171
#include "interpreter.def"
172
173
// two functions are defined from the macros above but never used
174
// these prototype declarations will prevent a warning
175
#if defined(__GNUC__)
176
void JR_IDLE(void) __attribute__((used));
177
void JALR_IDLE(void) __attribute__((used));
178
#endif
179
180
// -----------------------------------------------------------
181
// Flow control 'fake' instructions
182
// -----------------------------------------------------------
183
static void FIN_BLOCK(void)
184
{
185
if (!delay_slot)
186
{
187
jump_to((PC-1)->addr+4);
188
/*#ifdef DBG
189
if (g_DebuggerActive) update_debugger(PC->addr);
190
#endif
191
Used by dynarec only, check should be unnecessary
192
*/
193
PC->ops();
194
if (r4300emu == CORE_DYNAREC) dyna_jump();
195
}
196
else
197
{
198
precomp_block *blk = actual;
199
precomp_instr *inst = PC;
200
jump_to((PC-1)->addr+4);
201
202
/*#ifdef DBG
203
if (g_DebuggerActive) update_debugger(PC->addr);
204
#endif
205
Used by dynarec only, check should be unnecessary
206
*/
207
if (!skip_jump)
208
{
209
PC->ops();
210
actual = blk;
211
PC = inst+1;
212
}
213
else
214
PC->ops();
215
216
if (r4300emu == CORE_DYNAREC) dyna_jump();
217
}
218
}
219
220
static void NOTCOMPILED(void)
221
{
222
unsigned int *mem = fast_mem_access(blocks[PC->addr>>12]->start);
223
#ifdef CORE_DBG
224
DebugMessage(M64MSG_INFO, "NOTCOMPILED: addr = %x ops = %lx", PC->addr, (long) PC->ops);
225
#endif
226
227
if (mem != NULL)
228
recompile_block((int *)mem, blocks[PC->addr >> 12], PC->addr);
229
else
230
DebugMessage(M64MSG_ERROR, "not compiled exception");
231
232
/*#ifdef DBG
233
if (g_DebuggerActive) update_debugger(PC->addr);
234
#endif
235
The preceeding update_debugger SHOULD be unnecessary since it should have been
236
called before NOTCOMPILED would have been executed
237
*/
238
PC->ops();
239
if (r4300emu == CORE_DYNAREC)
240
dyna_jump();
241
}
242
243
static void NOTCOMPILED2(void)
244
{
245
NOTCOMPILED();
246
}
247
248
// -----------------------------------------------------------
249
// Cached interpreter instruction table
250
// -----------------------------------------------------------
251
const cpu_instruction_table cached_interpreter_table = {
252
LB,
253
LBU,
254
LH,
255
LHU,
256
LW,
257
LWL,
258
LWR,
259
SB,
260
SH,
261
SW,
262
SWL,
263
SWR,
264
265
LD,
266
LDL,
267
LDR,
268
LL,
269
LWU,
270
SC,
271
SD,
272
SDL,
273
SDR,
274
SYNC,
275
276
ADDI,
277
ADDIU,
278
SLTI,
279
SLTIU,
280
ANDI,
281
ORI,
282
XORI,
283
LUI,
284
285
DADDI,
286
DADDIU,
287
288
ADD,
289
ADDU,
290
SUB,
291
SUBU,
292
SLT,
293
SLTU,
294
AND,
295
OR,
296
XOR,
297
NOR,
298
299
DADD,
300
DADDU,
301
DSUB,
302
DSUBU,
303
304
MULT,
305
MULTU,
306
DIV,
307
DIVU,
308
MFHI,
309
MTHI,
310
MFLO,
311
MTLO,
312
313
DMULT,
314
DMULTU,
315
DDIV,
316
DDIVU,
317
318
J,
319
J_OUT,
320
J_IDLE,
321
JAL,
322
JAL_OUT,
323
JAL_IDLE,
324
// Use the _OUT versions of JR and JALR, since we don't know
325
// until runtime if they're going to jump inside or outside the block
326
JR_OUT,
327
JALR_OUT,
328
BEQ,
329
BEQ_OUT,
330
BEQ_IDLE,
331
BNE,
332
BNE_OUT,
333
BNE_IDLE,
334
BLEZ,
335
BLEZ_OUT,
336
BLEZ_IDLE,
337
BGTZ,
338
BGTZ_OUT,
339
BGTZ_IDLE,
340
BLTZ,
341
BLTZ_OUT,
342
BLTZ_IDLE,
343
BGEZ,
344
BGEZ_OUT,
345
BGEZ_IDLE,
346
BLTZAL,
347
BLTZAL_OUT,
348
BLTZAL_IDLE,
349
BGEZAL,
350
BGEZAL_OUT,
351
BGEZAL_IDLE,
352
353
BEQL,
354
BEQL_OUT,
355
BEQL_IDLE,
356
BNEL,
357
BNEL_OUT,
358
BNEL_IDLE,
359
BLEZL,
360
BLEZL_OUT,
361
BLEZL_IDLE,
362
BGTZL,
363
BGTZL_OUT,
364
BGTZL_IDLE,
365
BLTZL,
366
BLTZL_OUT,
367
BLTZL_IDLE,
368
BGEZL,
369
BGEZL_OUT,
370
BGEZL_IDLE,
371
BLTZALL,
372
BLTZALL_OUT,
373
BLTZALL_IDLE,
374
BGEZALL,
375
BGEZALL_OUT,
376
BGEZALL_IDLE,
377
BC1TL,
378
BC1TL_OUT,
379
BC1TL_IDLE,
380
BC1FL,
381
BC1FL_OUT,
382
BC1FL_IDLE,
383
384
SLL,
385
SRL,
386
SRA,
387
SLLV,
388
SRLV,
389
SRAV,
390
391
DSLL,
392
DSRL,
393
DSRA,
394
DSLLV,
395
DSRLV,
396
DSRAV,
397
DSLL32,
398
DSRL32,
399
DSRA32,
400
401
MTC0,
402
MFC0,
403
404
TLBR,
405
TLBWI,
406
TLBWR,
407
TLBP,
408
CACHE,
409
ERET,
410
411
LWC1,
412
SWC1,
413
MTC1,
414
MFC1,
415
CTC1,
416
CFC1,
417
BC1T,
418
BC1T_OUT,
419
BC1T_IDLE,
420
BC1F,
421
BC1F_OUT,
422
BC1F_IDLE,
423
424
DMFC1,
425
DMTC1,
426
LDC1,
427
SDC1,
428
429
CVT_S_D,
430
CVT_S_W,
431
CVT_S_L,
432
CVT_D_S,
433
CVT_D_W,
434
CVT_D_L,
435
CVT_W_S,
436
CVT_W_D,
437
CVT_L_S,
438
CVT_L_D,
439
440
ROUND_W_S,
441
ROUND_W_D,
442
ROUND_L_S,
443
ROUND_L_D,
444
445
TRUNC_W_S,
446
TRUNC_W_D,
447
TRUNC_L_S,
448
TRUNC_L_D,
449
450
CEIL_W_S,
451
CEIL_W_D,
452
CEIL_L_S,
453
CEIL_L_D,
454
455
FLOOR_W_S,
456
FLOOR_W_D,
457
FLOOR_L_S,
458
FLOOR_L_D,
459
460
ADD_S,
461
ADD_D,
462
463
SUB_S,
464
SUB_D,
465
466
MUL_S,
467
MUL_D,
468
469
DIV_S,
470
DIV_D,
471
472
ABS_S,
473
ABS_D,
474
475
MOV_S,
476
MOV_D,
477
478
NEG_S,
479
NEG_D,
480
481
SQRT_S,
482
SQRT_D,
483
484
C_F_S,
485
C_F_D,
486
C_UN_S,
487
C_UN_D,
488
C_EQ_S,
489
C_EQ_D,
490
C_UEQ_S,
491
C_UEQ_D,
492
C_OLT_S,
493
C_OLT_D,
494
C_ULT_S,
495
C_ULT_D,
496
C_OLE_S,
497
C_OLE_D,
498
C_ULE_S,
499
C_ULE_D,
500
C_SF_S,
501
C_SF_D,
502
C_NGLE_S,
503
C_NGLE_D,
504
C_SEQ_S,
505
C_SEQ_D,
506
C_NGL_S,
507
C_NGL_D,
508
C_LT_S,
509
C_LT_D,
510
C_NGE_S,
511
C_NGE_D,
512
C_LE_S,
513
C_LE_D,
514
C_NGT_S,
515
C_NGT_D,
516
517
SYSCALL,
518
519
TEQ,
520
521
NOP,
522
RESERVED,
523
NI,
524
525
FIN_BLOCK,
526
NOTCOMPILED,
527
NOTCOMPILED2
528
};
529
530
cpu_instruction_table current_instruction_table;
531
532
static unsigned int update_invalid_addr(unsigned int addr)
533
{
534
if (addr >= 0x80000000 && addr < 0xa0000000)
535
{
536
if (invalid_code[addr>>12]) invalid_code[(addr+0x20000000)>>12] = 1;
537
if (invalid_code[(addr+0x20000000)>>12]) invalid_code[addr>>12] = 1;
538
return addr;
539
}
540
else if (addr >= 0xa0000000 && addr < 0xc0000000)
541
{
542
if (invalid_code[addr>>12]) invalid_code[(addr-0x20000000)>>12] = 1;
543
if (invalid_code[(addr-0x20000000)>>12]) invalid_code[addr>>12] = 1;
544
return addr;
545
}
546
else
547
{
548
unsigned int paddr = virtual_to_physical_address(addr, 2);
549
if (paddr)
550
{
551
unsigned int beg_paddr = paddr - (addr - (addr&~0xFFF));
552
update_invalid_addr(paddr);
553
if (invalid_code[(beg_paddr+0x000)>>12]) invalid_code[addr>>12] = 1;
554
if (invalid_code[(beg_paddr+0xFFC)>>12]) invalid_code[addr>>12] = 1;
555
if (invalid_code[addr>>12]) invalid_code[(beg_paddr+0x000)>>12] = 1;
556
if (invalid_code[addr>>12]) invalid_code[(beg_paddr+0xFFC)>>12] = 1;
557
}
558
return paddr;
559
}
560
}
561
562
#define addr jump_to_address
563
unsigned int jump_to_address;
564
void jump_to_func(void)
565
{
566
unsigned int paddr;
567
if (skip_jump) return;
568
paddr = update_invalid_addr(addr);
569
if (!paddr) return;
570
actual = blocks[addr>>12];
571
if (invalid_code[addr>>12])
572
{
573
if (!blocks[addr>>12])
574
{
575
blocks[addr>>12] = (precomp_block *) malloc(sizeof(precomp_block));
576
actual = blocks[addr>>12];
577
blocks[addr>>12]->code = NULL;
578
blocks[addr>>12]->block = NULL;
579
blocks[addr>>12]->jumps_table = NULL;
580
blocks[addr>>12]->riprel_table = NULL;
581
}
582
blocks[addr>>12]->start = addr & ~0xFFF;
583
blocks[addr>>12]->end = (addr & ~0xFFF) + 0x1000;
584
init_block(blocks[addr>>12]);
585
}
586
PC=actual->block+((addr-actual->start)>>2);
587
588
if (r4300emu == CORE_DYNAREC) dyna_jump();
589
}
590
#undef addr
591
592
void generic_jump_to(unsigned int address)
593
{
594
if (r4300emu == CORE_PURE_INTERPRETER)
595
PC->addr = address;
596
else {
597
#ifdef NEW_DYNAREC
598
if (r4300emu == CORE_DYNAREC)
599
last_addr = pcaddr;
600
else
601
jump_to(address);
602
#else
603
jump_to(address);
604
#endif
605
}
606
}
607
608
/* Refer to Figure 6-2 on page 155 and explanation on page B-11
609
of MIPS R4000 Microprocessor User's Manual (Second Edition)
610
by Joe Heinrich.
611
*/
612
void shuffle_fpr_data(int oldStatus, int newStatus)
613
{
614
#if defined(M64P_BIG_ENDIAN)
615
const int isBigEndian = 1;
616
#else
617
const int isBigEndian = 0;
618
#endif
619
620
if ((newStatus & 0x04000000) != (oldStatus & 0x04000000))
621
{
622
int i;
623
int temp_fgr_32[32];
624
625
// pack or unpack the FGR register data
626
if (newStatus & 0x04000000)
627
{ // switching into 64-bit mode
628
// retrieve 32 FPR values from packed 32-bit FGR registers
629
for (i = 0; i < 32; i++)
630
{
631
temp_fgr_32[i] = *((int *) &reg_cop1_fgr_64[i>>1] + ((i & 1) ^ isBigEndian));
632
}
633
// unpack them into 32 64-bit registers, taking the high 32-bits from their temporary place in the upper 16 FGRs
634
for (i = 0; i < 32; i++)
635
{
636
int high32 = *((int *) &reg_cop1_fgr_64[(i>>1)+16] + (i & 1));
637
*((int *) &reg_cop1_fgr_64[i] + isBigEndian) = temp_fgr_32[i];
638
*((int *) &reg_cop1_fgr_64[i] + (isBigEndian^1)) = high32;
639
}
640
}
641
else
642
{ // switching into 32-bit mode
643
// retrieve the high 32 bits from each 64-bit FGR register and store in temp array
644
for (i = 0; i < 32; i++)
645
{
646
temp_fgr_32[i] = *((int *) &reg_cop1_fgr_64[i] + (isBigEndian^1));
647
}
648
// take the low 32 bits from each register and pack them together into 64-bit pairs
649
for (i = 0; i < 16; i++)
650
{
651
unsigned int least32 = *((unsigned int *) &reg_cop1_fgr_64[i*2] + isBigEndian);
652
unsigned int most32 = *((unsigned int *) &reg_cop1_fgr_64[i*2+1] + isBigEndian);
653
reg_cop1_fgr_64[i] = ((unsigned long long) most32 << 32) | (unsigned long long) least32;
654
}
655
// store the high bits in the upper 16 FGRs, which wont be accessible in 32-bit mode
656
for (i = 0; i < 32; i++)
657
{
658
*((int *) &reg_cop1_fgr_64[(i>>1)+16] + (i & 1)) = temp_fgr_32[i];
659
}
660
}
661
}
662
}
663
664
void set_fpr_pointers(int newStatus)
665
{
666
int i;
667
#if defined(M64P_BIG_ENDIAN)
668
const int isBigEndian = 1;
669
#else
670
const int isBigEndian = 0;
671
#endif
672
673
// update the FPR register pointers
674
if (newStatus & 0x04000000)
675
{
676
for (i = 0; i < 32; i++)
677
{
678
reg_cop1_double[i] = (double*) &reg_cop1_fgr_64[i];
679
reg_cop1_simple[i] = ((float*) &reg_cop1_fgr_64[i]) + isBigEndian;
680
}
681
}
682
else
683
{
684
for (i = 0; i < 32; i++)
685
{
686
reg_cop1_double[i] = (double*) &reg_cop1_fgr_64[i>>1];
687
reg_cop1_simple[i] = ((float*) &reg_cop1_fgr_64[i>>1]) + ((i & 1) ^ isBigEndian);
688
}
689
}
690
}
691
692
int check_cop1_unusable(void)
693
{
694
if (!(Status & 0x20000000))
695
{
696
Cause = (11 << 2) | 0x10000000;
697
exception_general();
698
return 1;
699
}
700
return 0;
701
}
702
703
void update_count(void)
704
{
705
#ifdef NEW_DYNAREC
706
if (r4300emu != CORE_DYNAREC)
707
{
708
#endif
709
Count = Count + (PC->addr - last_addr)/2;
710
last_addr = PC->addr;
711
#ifdef NEW_DYNAREC
712
}
713
#endif
714
715
#ifdef COMPARE_CORE
716
if (delay_slot)
717
CoreCompareCallback();
718
#endif
719
/*#ifdef DBG
720
if (g_DebuggerActive && !delay_slot) update_debugger(PC->addr);
721
#endif
722
*/
723
}
724
725
void init_blocks(void)
726
{
727
int i;
728
for (i=0; i<0x100000; i++)
729
{
730
invalid_code[i] = 1;
731
blocks[i] = NULL;
732
}
733
}
734
735
void free_blocks(void)
736
{
737
int i;
738
for (i=0; i<0x100000; i++)
739
{
740
if (blocks[i])
741
{
742
free_block(blocks[i]);
743
free(blocks[i]);
744
blocks[i] = NULL;
745
}
746
}
747
}
748
749
/* this hard reset function simulates the boot-up state of the R4300 CPU */
750
void r4300_reset_hard(void)
751
{
752
unsigned int i;
753
754
// clear r4300 registers and TLB entries
755
for (i = 0; i < 32; i++)
756
{
757
reg[i]=0;
758
reg_cop0[i]=0;
759
reg_cop1_fgr_64[i]=0;
760
761
// --------------tlb------------------------
762
tlb_e[i].mask=0;
763
tlb_e[i].vpn2=0;
764
tlb_e[i].g=0;
765
tlb_e[i].asid=0;
766
tlb_e[i].pfn_even=0;
767
tlb_e[i].c_even=0;
768
tlb_e[i].d_even=0;
769
tlb_e[i].v_even=0;
770
tlb_e[i].pfn_odd=0;
771
tlb_e[i].c_odd=0;
772
tlb_e[i].d_odd=0;
773
tlb_e[i].v_odd=0;
774
tlb_e[i].r=0;
775
//tlb_e[i].check_parity_mask=0x1000;
776
777
tlb_e[i].start_even=0;
778
tlb_e[i].end_even=0;
779
tlb_e[i].phys_even=0;
780
tlb_e[i].start_odd=0;
781
tlb_e[i].end_odd=0;
782
tlb_e[i].phys_odd=0;
783
}
784
for (i=0; i<0x100000; i++)
785
{
786
tlb_LUT_r[i] = 0;
787
tlb_LUT_w[i] = 0;
788
}
789
llbit=0;
790
hi=0;
791
lo=0;
792
FCR0=0x511;
793
FCR31=0;
794
795
// set COP0 registers
796
Random = 31;
797
Status= 0x34000000;
798
set_fpr_pointers(Status);
799
Config= 0x6e463;
800
PRevID = 0xb00;
801
Count = 0x5000;
802
Cause = 0x5C;
803
Context = 0x7FFFF0;
804
EPC = 0xFFFFFFFF;
805
BadVAddr = 0xFFFFFFFF;
806
ErrorEPC = 0xFFFFFFFF;
807
808
rounding_mode = 0x33F;
809
}
810
811
/* this soft reset function simulates the actions of the PIF ROM, which may vary by region
812
* TODO: accurately simulate the effects of the PIF ROM in the case of a soft reset
813
* (e.g. Goldeneye crashes) */
814
void r4300_reset_soft(void)
815
{
816
long long CRC = 0;
817
unsigned int i;
818
819
// copy boot code from ROM to SP_DMEM
820
memcpy((char *)SP_DMEM+0x40, rom+0x40, 0xFC0);
821
822
// the following values are extracted from the pj64 source code
823
// thanks to Zilmar and Jabo
824
825
reg[6] = 0xFFFFFFFFA4001F0CLL;
826
reg[7] = 0xFFFFFFFFA4001F08LL;
827
reg[8] = 0x00000000000000C0LL;
828
reg[10]= 0x0000000000000040LL;
829
reg[11]= 0xFFFFFFFFA4000040LL;
830
reg[29]= 0xFFFFFFFFA4001FF0LL;
831
832
// figure out which ROM type is loaded
833
for (i = 0x40/4; i < (0x1000/4); i++)
834
CRC += SP_DMEM[i];
835
switch(CRC) {
836
case 0x000000D0027FDF31LL:
837
case 0x000000CFFB631223LL:
838
CIC_Chip = 1;
839
break;
840
case 0x000000D057C85244LL:
841
CIC_Chip = 2;
842
break;
843
case 0x000000D6497E414BLL:
844
CIC_Chip = 3;
845
break;
846
case 0x0000011A49F60E96LL:
847
CIC_Chip = 5;
848
break;
849
case 0x000000D6D5BE5580LL:
850
CIC_Chip = 6;
851
break;
852
default:
853
CIC_Chip = 2;
854
}
855
856
switch(ROM_PARAMS.systemtype)
857
{
858
case SYSTEM_PAL:
859
switch (CIC_Chip) {
860
case 2:
861
reg[5] = 0xFFFFFFFFC0F1D859LL;
862
reg[14]= 0x000000002DE108EALL;
863
break;
864
case 3:
865
reg[5] = 0xFFFFFFFFD4646273LL;
866
reg[14]= 0x000000001AF99984LL;
867
break;
868
case 5:
869
SP_IMEM[1] = 0xBDA807FC;
870
reg[5] = 0xFFFFFFFFDECAAAD1LL;
871
reg[14]= 0x000000000CF85C13LL;
872
reg[24]= 0x0000000000000002LL;
873
break;
874
case 6:
875
reg[5] = 0xFFFFFFFFB04DC903LL;
876
reg[14]= 0x000000001AF99984LL;
877
reg[24]= 0x0000000000000002LL;
878
break;
879
}
880
reg[23]= 0x0000000000000006LL;
881
reg[31]= 0xFFFFFFFFA4001554LL;
882
break;
883
case SYSTEM_NTSC:
884
default:
885
switch (CIC_Chip) {
886
case 2:
887
reg[5] = 0xFFFFFFFFC95973D5LL;
888
reg[14]= 0x000000002449A366LL;
889
break;
890
case 3:
891
reg[5] = 0xFFFFFFFF95315A28LL;
892
reg[14]= 0x000000005BACA1DFLL;
893
break;
894
case 5:
895
SP_IMEM[1] = 0x8DA807FC;
896
reg[5] = 0x000000005493FB9ALL;
897
reg[14]= 0xFFFFFFFFC2C20384LL;
898
break;
899
case 6:
900
reg[5] = 0xFFFFFFFFE067221FLL;
901
reg[14]= 0x000000005CD2B70FLL;
902
break;
903
}
904
reg[20]= 0x0000000000000001LL;
905
reg[24]= 0x0000000000000003LL;
906
reg[31]= 0xFFFFFFFFA4001550LL;
907
}
908
switch (CIC_Chip) {
909
case 1:
910
reg[22]= 0x000000000000003FLL;
911
break;
912
case 2:
913
reg[1] = 0x0000000000000001LL;
914
reg[2] = 0x000000000EBDA536LL;
915
reg[3] = 0x000000000EBDA536LL;
916
reg[4] = 0x000000000000A536LL;
917
reg[12]= 0xFFFFFFFFED10D0B3LL;
918
reg[13]= 0x000000001402A4CCLL;
919
reg[15]= 0x000000003103E121LL;
920
reg[22]= 0x000000000000003FLL;
921
reg[25]= 0xFFFFFFFF9DEBB54FLL;
922
break;
923
case 3:
924
reg[1] = 0x0000000000000001LL;
925
reg[2] = 0x0000000049A5EE96LL;
926
reg[3] = 0x0000000049A5EE96LL;
927
reg[4] = 0x000000000000EE96LL;
928
reg[12]= 0xFFFFFFFFCE9DFBF7LL;
929
reg[13]= 0xFFFFFFFFCE9DFBF7LL;
930
reg[15]= 0x0000000018B63D28LL;
931
reg[22]= 0x0000000000000078LL;
932
reg[25]= 0xFFFFFFFF825B21C9LL;
933
break;
934
case 5:
935
SP_IMEM[0] = 0x3C0DBFC0;
936
SP_IMEM[2] = 0x25AD07C0;
937
SP_IMEM[3] = 0x31080080;
938
SP_IMEM[4] = 0x5500FFFC;
939
SP_IMEM[5] = 0x3C0DBFC0;
940
SP_IMEM[6] = 0x8DA80024;
941
SP_IMEM[7] = 0x3C0BB000;
942
reg[2] = 0xFFFFFFFFF58B0FBFLL;
943
reg[3] = 0xFFFFFFFFF58B0FBFLL;
944
reg[4] = 0x0000000000000FBFLL;
945
reg[12]= 0xFFFFFFFF9651F81ELL;
946
reg[13]= 0x000000002D42AAC5LL;
947
reg[15]= 0x0000000056584D60LL;
948
reg[22]= 0x0000000000000091LL;
949
reg[25]= 0xFFFFFFFFCDCE565FLL;
950
break;
951
case 6:
952
reg[2] = 0xFFFFFFFFA95930A4LL;
953
reg[3] = 0xFFFFFFFFA95930A4LL;
954
reg[4] = 0x00000000000030A4LL;
955
reg[12]= 0xFFFFFFFFBCB59510LL;
956
reg[13]= 0xFFFFFFFFBCB59510LL;
957
reg[15]= 0x000000007A3C07F4LL;
958
reg[22]= 0x0000000000000085LL;
959
reg[25]= 0x00000000465E3F72LL;
960
break;
961
}
962
963
}
964
965
#if !defined(NO_ASM)
966
static void dynarec_setup_code(void)
967
{
968
// The dynarec jumps here after we call dyna_start and it prepares
969
// Here we need to prepare the initial code block and jump to it
970
jump_to(0xa4000040);
971
972
// Prevent segfault on failed jump_to
973
if (!actual->block || !actual->code)
974
dyna_stop();
975
}
976
#endif
977
978
void r4300_execute(void (*startcb)(void))
979
{
980
#if defined(COUNT_INSTR) || (defined(DYNAREC) && defined(PROFILE_R4300))
981
unsigned int i;
982
#endif
983
984
current_instruction_table = cached_interpreter_table;
985
986
debug_count = 0;
987
delay_slot=0;
988
stop = 0;
989
//rompause = 1;
990
rompausesem = CreateSemaphore(NULL, 0, 1, NULL);
991
992
/* clear instruction counters */
993
#if defined(COUNT_INSTR)
994
for (i = 0; i < 131; i++)
995
instr_count[i] = 0;
996
#endif
997
998
last_addr = 0xa4000040;
999
next_interupt = 624999;
1000
init_interupt();
1001
1002
if (startcb)
1003
startcb();
1004
1005
// now that everything has been set up, we stop here to wait for the first frame
1006
WaitForSingleObject(rompausesem, INFINITE);
1007
1008
if (r4300emu == CORE_PURE_INTERPRETER)
1009
{
1010
DebugMessage(M64MSG_INFO, "Starting R4300 emulator: Pure Interpreter");
1011
r4300emu = CORE_PURE_INTERPRETER;
1012
pure_interpreter();
1013
}
1014
#if defined(DYNAREC)
1015
else if (r4300emu >= 2)
1016
{
1017
DebugMessage(M64MSG_INFO, "Starting R4300 emulator: Dynamic Recompiler");
1018
r4300emu = CORE_DYNAREC;
1019
init_blocks();
1020
1021
#ifdef NEW_DYNAREC
1022
new_dynarec_init();
1023
new_dyna_start();
1024
new_dynarec_cleanup();
1025
#else
1026
dyna_start(dynarec_setup_code);
1027
PC++;
1028
#endif
1029
#if defined(PROFILE_R4300)
1030
pfProfile = fopen("instructionaddrs.dat", "ab");
1031
for (i=0; i<0x100000; i++)
1032
if (invalid_code[i] == 0 && blocks[i] != NULL && blocks[i]->code != NULL && blocks[i]->block != NULL)
1033
{
1034
unsigned char *x86addr;
1035
int mipsop;
1036
// store final code length for this block
1037
mipsop = -1; /* -1 == end of x86 code block */
1038
x86addr = blocks[i]->code + blocks[i]->code_length;
1039
if (fwrite(&mipsop, 1, 4, pfProfile) != 4 ||
1040
fwrite(&x86addr, 1, sizeof(char *), pfProfile) != sizeof(char *))
1041
DebugMessage(M64MSG_ERROR, "Error writing R4300 instruction address profiling data");
1042
}
1043
fclose(pfProfile);
1044
pfProfile = NULL;
1045
#endif
1046
free_blocks();
1047
}
1048
#endif
1049
else /* if (r4300emu == CORE_INTERPRETER) */
1050
{
1051
DebugMessage(M64MSG_INFO, "Starting R4300 emulator: Cached Interpreter");
1052
r4300emu = CORE_INTERPRETER;
1053
init_blocks();
1054
jump_to(0xa4000040);
1055
1056
/* Prevent segfault on failed jump_to */
1057
if (!actual->block)
1058
return;
1059
1060
last_addr = PC->addr;
1061
while (!stop)
1062
{
1063
#ifdef COMPARE_CORE
1064
if (PC->ops == FIN_BLOCK && (PC->addr < 0x80000000 || PC->addr >= 0xc0000000))
1065
virtual_to_physical_address(PC->addr, 2);
1066
CoreCompareCallback();
1067
#endif
1068
#ifdef DBG
1069
if (g_DebuggerActive) update_debugger(PC->addr, -1);
1070
#endif
1071
TRACECB();
1072
PC->ops();
1073
}
1074
1075
free_blocks();
1076
}
1077
1078
debug_count+= Count;
1079
DebugMessage(M64MSG_INFO, "R4300 emulator finished.");
1080
1081
/* print instruction counts */
1082
#if defined(COUNT_INSTR)
1083
if (r4300emu == CORE_DYNAREC)
1084
{
1085
unsigned int iTypeCount[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
1086
unsigned int iTotal = 0;
1087
char line[128], param[24];
1088
DebugMessage(M64MSG_INFO, "Instruction counters:");
1089
line[0] = 0;
1090
for (i = 0; i < 131; i++)
1091
{
1092
sprintf(param, "%8s: %08i ", instr_name[i], instr_count[i]);
1093
strcat(line, param);
1094
if (i % 5 == 4)
1095
{
1096
DebugMessage(M64MSG_INFO, "%s", line);
1097
line[0] = 0;
1098
}
1099
iTypeCount[instr_type[i]] += instr_count[i];
1100
iTotal += instr_count[i];
1101
}
1102
DebugMessage(M64MSG_INFO, "Instruction type summary (total instructions = %i)", iTotal);
1103
for (i = 0; i < 11; i++)
1104
{
1105
DebugMessage(M64MSG_INFO, "%20s: %04.1f%% (%i)", instr_typename[i], (float) iTypeCount[i] * 100.0 / iTotal, iTypeCount[i]);
1106
}
1107
}
1108
#endif
1109
}
1110
1111
EXPORT void CALL GetRegisters(unsigned char * dest)
1112
{
1113
memcpy(dest, reg, 8 * 32);
1114
dest += 8 * 32;
1115
1116
if (PC != NULL)
1117
{
1118
memcpy(dest, &(PC->addr), 4);
1119
}
1120
else
1121
{
1122
char stupid[] = "0000";
1123
memcpy(dest, stupid, 4);
1124
}
1125
1126
dest += 4;
1127
1128
memcpy(dest, &llbit, 4);
1129
dest += 4;
1130
memcpy(dest, &lo, 8);
1131
dest += 8;
1132
memcpy(dest, &hi, 8);
1133
dest += 8;
1134
memcpy(dest, &FCR0, 4);
1135
dest += 4;
1136
memcpy(dest, &FCR31, 4);
1137
dest += 4;
1138
1139
memcpy(dest, reg_cop0, 4 * 32);
1140
dest += 4 * 32;
1141
1142
memcpy(dest, reg_cop1_fgr_64, 8 * 32);
1143
dest += 8 * 32;
1144
1145
}
1146