drc: minor adjustments
[pcsx_rearmed.git] / libpcsxcore / psxinterpreter.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
18 ***************************************************************************/
19
20/*
21 * PSX assembly interpreter.
22 */
23
24#include "psxcommon.h"
25#include "r3000a.h"
26#include "gte.h"
27#include "psxhle.h"
fc8145b7 28#include "debug.h"
3968e69e 29#include "psxinterpreter.h"
32631e6a 30#include <assert.h>
ef79bbde
P
31
32static int branch = 0;
33static int branch2 = 0;
34static u32 branchPC;
35
36// These macros are used to assemble the repassembler functions
37
38#ifdef PSXCPU_LOG
39#define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
40#else
41#define debugI()
42#endif
43
ef79bbde
P
44// Subsets
45void (*psxBSC[64])();
46void (*psxSPC[64])();
47void (*psxREG[32])();
48void (*psxCP0[32])();
6c0eefaf 49void (*psxCP2[64])(struct psxCP2Regs *regs);
ef79bbde
P
50void (*psxCP2BSC[32])();
51
943a507a 52#ifdef ICACHE_EMULATION
53/*
54Formula One 2001 :
55Use old CPU cache code when the RAM location is updated with new code (affects in-game racing)
56*/
57static u8* ICache_Addr;
58static u8* ICache_Code;
59uint32_t *Read_ICache(uint32_t pc)
60{
61 uint32_t pc_bank, pc_offset, pc_cache;
62 uint8_t *IAddr, *ICode;
63
64 pc_bank = pc >> 24;
65 pc_offset = pc & 0xffffff;
66 pc_cache = pc & 0xfff;
67
68 IAddr = ICache_Addr;
69 ICode = ICache_Code;
70
71 // cached - RAM
72 if (pc_bank == 0x80 || pc_bank == 0x00)
73 {
74 if (SWAP32(*(uint32_t *)(IAddr + pc_cache)) == pc_offset)
75 {
76 // Cache hit - return last opcode used
77 return (uint32_t *)(ICode + pc_cache);
78 }
79 else
80 {
81 // Cache miss - addresses don't match
82 // - default: 0xffffffff (not init)
83
84 // cache line is 4 bytes wide
85 pc_offset &= ~0xf;
86 pc_cache &= ~0xf;
87
88 // address line
89 *(uint32_t *)(IAddr + pc_cache + 0x0) = SWAP32(pc_offset + 0x0);
90 *(uint32_t *)(IAddr + pc_cache + 0x4) = SWAP32(pc_offset + 0x4);
91 *(uint32_t *)(IAddr + pc_cache + 0x8) = SWAP32(pc_offset + 0x8);
92 *(uint32_t *)(IAddr + pc_cache + 0xc) = SWAP32(pc_offset + 0xc);
93
94 // opcode line
95 pc_offset = pc & ~0xf;
96 *(uint32_t *)(ICode + pc_cache + 0x0) = psxMu32ref(pc_offset + 0x0);
97 *(uint32_t *)(ICode + pc_cache + 0x4) = psxMu32ref(pc_offset + 0x4);
98 *(uint32_t *)(ICode + pc_cache + 0x8) = psxMu32ref(pc_offset + 0x8);
99 *(uint32_t *)(ICode + pc_cache + 0xc) = psxMu32ref(pc_offset + 0xc);
100 }
101 }
102
103 /*
104 TODO: Probably should add cached BIOS
105 */
106 // default
107 return (uint32_t *)PSXM(pc);
108}
109#endif
110
ef79bbde
P
111static void delayRead(int reg, u32 bpc) {
112 u32 rold, rnew;
113
114// SysPrintf("delayRead at %x!\n", psxRegs.pc);
115
116 rold = psxRegs.GPR.r[reg];
117 psxBSC[psxRegs.code >> 26](); // branch delay load
118 rnew = psxRegs.GPR.r[reg];
119
120 psxRegs.pc = bpc;
121
abbc1ca1 122 branch = 0;
ef79bbde
P
123
124 psxRegs.GPR.r[reg] = rold;
125 execI(); // first branch opcode
126 psxRegs.GPR.r[reg] = rnew;
127
abbc1ca1 128 psxBranchTest();
ef79bbde
P
129}
130
131static void delayWrite(int reg, u32 bpc) {
132
133/* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
134
135 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
136 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
137
138 // no changes from normal behavior
139
140 psxBSC[psxRegs.code >> 26]();
141
142 branch = 0;
143 psxRegs.pc = bpc;
144
145 psxBranchTest();
146}
147
148static void delayReadWrite(int reg, u32 bpc) {
149
150// SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
151
152 // the branch delay load is skipped
153
154 branch = 0;
155 psxRegs.pc = bpc;
156
157 psxBranchTest();
158}
159
160// this defines shall be used with the tmp
161// of the next func (instead of _Funct_...)
162#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
163#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
164#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
165#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
166#define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
167
168int psxTestLoadDelay(int reg, u32 tmp) {
169 if (tmp == 0) return 0; // NOP
170 switch (tmp >> 26) {
171 case 0x00: // SPECIAL
172 switch (_tFunct_) {
173 case 0x00: // SLL
174 case 0x02: case 0x03: // SRL/SRA
175 if (_tRd_ == reg && _tRt_ == reg) return 1; else
176 if (_tRt_ == reg) return 2; else
177 if (_tRd_ == reg) return 3;
178 break;
179
180 case 0x08: // JR
181 if (_tRs_ == reg) return 2;
182 break;
183 case 0x09: // JALR
184 if (_tRd_ == reg && _tRs_ == reg) return 1; else
185 if (_tRs_ == reg) return 2; else
186 if (_tRd_ == reg) return 3;
187 break;
188
189 // SYSCALL/BREAK just a break;
190
191 case 0x20: case 0x21: case 0x22: case 0x23:
192 case 0x24: case 0x25: case 0x26: case 0x27:
193 case 0x2a: case 0x2b: // ADD/ADDU...
194 case 0x04: case 0x06: case 0x07: // SLLV...
195 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
196 if (_tRt_ == reg || _tRs_ == reg) return 2; else
197 if (_tRd_ == reg) return 3;
198 break;
199
200 case 0x10: case 0x12: // MFHI/MFLO
201 if (_tRd_ == reg) return 3;
202 break;
203 case 0x11: case 0x13: // MTHI/MTLO
204 if (_tRs_ == reg) return 2;
205 break;
206
207 case 0x18: case 0x19:
208 case 0x1a: case 0x1b: // MULT/DIV...
209 if (_tRt_ == reg || _tRs_ == reg) return 2;
210 break;
211 }
212 break;
213
214 case 0x01: // REGIMM
215 switch (_tRt_) {
862bfc0d 216 case 0x00: case 0x01:
217 case 0x10: case 0x11: // BLTZ/BGEZ...
218 // Xenogears - lbu v0 / beq v0
219 // - no load delay (fixes battle loading)
220 break;
221
ef79bbde
P
222 if (_tRs_ == reg) return 2;
223 break;
224 }
225 break;
226
227 // J would be just a break;
228 case 0x03: // JAL
229 if (31 == reg) return 3;
230 break;
231
232 case 0x04: case 0x05: // BEQ/BNE
862bfc0d 233 // Xenogears - lbu v0 / beq v0
234 // - no load delay (fixes battle loading)
235 break;
236
ef79bbde
P
237 if (_tRs_ == reg || _tRt_ == reg) return 2;
238 break;
239
240 case 0x06: case 0x07: // BLEZ/BGTZ
862bfc0d 241 // Xenogears - lbu v0 / beq v0
242 // - no load delay (fixes battle loading)
243 break;
244
ef79bbde
P
245 if (_tRs_ == reg) return 2;
246 break;
247
248 case 0x08: case 0x09: case 0x0a: case 0x0b:
249 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
250 if (_tRt_ == reg && _tRs_ == reg) return 1; else
251 if (_tRs_ == reg) return 2; else
252 if (_tRt_ == reg) return 3;
253 break;
254
255 case 0x0f: // LUI
256 if (_tRt_ == reg) return 3;
257 break;
258
259 case 0x10: // COP0
260 switch (_tFunct_) {
261 case 0x00: // MFC0
262 if (_tRt_ == reg) return 3;
263 break;
264 case 0x02: // CFC0
265 if (_tRt_ == reg) return 3;
266 break;
267 case 0x04: // MTC0
268 if (_tRt_ == reg) return 2;
269 break;
270 case 0x06: // CTC0
271 if (_tRt_ == reg) return 2;
272 break;
273 // RFE just a break;
274 }
275 break;
276
277 case 0x12: // COP2
278 switch (_tFunct_) {
279 case 0x00:
280 switch (_tRs_) {
281 case 0x00: // MFC2
282 if (_tRt_ == reg) return 3;
283 break;
284 case 0x02: // CFC2
285 if (_tRt_ == reg) return 3;
286 break;
287 case 0x04: // MTC2
288 if (_tRt_ == reg) return 2;
289 break;
290 case 0x06: // CTC2
291 if (_tRt_ == reg) return 2;
292 break;
293 }
294 break;
295 // RTPS... break;
296 }
297 break;
298
299 case 0x22: case 0x26: // LWL/LWR
300 if (_tRt_ == reg) return 3; else
301 if (_tRs_ == reg) return 2;
302 break;
303
304 case 0x20: case 0x21: case 0x23:
305 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
306 if (_tRt_ == reg && _tRs_ == reg) return 1; else
307 if (_tRs_ == reg) return 2; else
308 if (_tRt_ == reg) return 3;
309 break;
310
311 case 0x28: case 0x29: case 0x2a:
312 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
313 if (_tRt_ == reg || _tRs_ == reg) return 2;
314 break;
315
316 case 0x32: case 0x3a: // LWC2/SWC2
317 if (_tRs_ == reg) return 2;
318 break;
319 }
320
321 return 0;
322}
323
324void psxDelayTest(int reg, u32 bpc) {
325 u32 *code;
326 u32 tmp;
327
943a507a 328 #ifdef ICACHE_EMULATION
329 if (Config.icache_emulation)
330 {
331 code = Read_ICache(psxRegs.pc);
332 }
333 else
334 #endif
335 {
336 code = (u32 *)PSXM(psxRegs.pc);
337 }
338
ef79bbde
P
339 tmp = ((code == NULL) ? 0 : SWAP32(*code));
340 branch = 1;
341
342 switch (psxTestLoadDelay(reg, tmp)) {
343 case 1:
344 delayReadWrite(reg, bpc); return;
345 case 2:
346 delayRead(reg, bpc); return;
347 case 3:
348 delayWrite(reg, bpc); return;
349 }
350 psxBSC[psxRegs.code >> 26]();
351
352 branch = 0;
353 psxRegs.pc = bpc;
354
355 psxBranchTest();
356}
357
990cb018 358static u32 psxBranchNoDelay(void) {
359 u32 *code;
360 u32 temp;
361
943a507a 362 #ifdef ICACHE_EMULATION
363 if (Config.icache_emulation)
364 {
365 code = Read_ICache(psxRegs.pc);
366 }
367 else
368 #endif
369 {
370 code = (u32 *)PSXM(psxRegs.pc);
371 }
990cb018 372 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
373 switch (_Op_) {
374 case 0x00: // SPECIAL
375 switch (_Funct_) {
376 case 0x08: // JR
377 return _u32(_rRs_);
378 case 0x09: // JALR
379 temp = _u32(_rRs_);
380 if (_Rd_) { _SetLink(_Rd_); }
381 return temp;
382 }
383 break;
384 case 0x01: // REGIMM
385 switch (_Rt_) {
386 case 0x00: // BLTZ
387 if (_i32(_rRs_) < 0)
388 return _BranchTarget_;
389 break;
390 case 0x01: // BGEZ
391 if (_i32(_rRs_) >= 0)
392 return _BranchTarget_;
393 break;
394 case 0x08: // BLTZAL
395 if (_i32(_rRs_) < 0) {
396 _SetLink(31);
397 return _BranchTarget_;
398 }
399 break;
400 case 0x09: // BGEZAL
401 if (_i32(_rRs_) >= 0) {
402 _SetLink(31);
403 return _BranchTarget_;
404 }
405 break;
406 }
407 break;
408 case 0x02: // J
409 return _JumpTarget_;
410 case 0x03: // JAL
411 _SetLink(31);
412 return _JumpTarget_;
413 case 0x04: // BEQ
414 if (_i32(_rRs_) == _i32(_rRt_))
415 return _BranchTarget_;
416 break;
417 case 0x05: // BNE
418 if (_i32(_rRs_) != _i32(_rRt_))
419 return _BranchTarget_;
420 break;
421 case 0x06: // BLEZ
422 if (_i32(_rRs_) <= 0)
423 return _BranchTarget_;
424 break;
425 case 0x07: // BGTZ
426 if (_i32(_rRs_) > 0)
427 return _BranchTarget_;
428 break;
429 }
430
431 return (u32)-1;
432}
433
434static int psxDelayBranchExec(u32 tar) {
435 execI();
436
437 branch = 0;
438 psxRegs.pc = tar;
439 psxRegs.cycle += BIAS;
440 psxBranchTest();
441 return 1;
442}
443
444static int psxDelayBranchTest(u32 tar1) {
445 u32 tar2, tmp1, tmp2;
446
447 tar2 = psxBranchNoDelay();
448 if (tar2 == (u32)-1)
449 return 0;
450
451 debugI();
452
453 /*
454 * Branch in delay slot:
455 * - execute 1 instruction at tar1
456 * - jump to tar2 (target of branch in delay slot; this branch
457 * has no normal delay slot, instruction at tar1 was fetched instead)
458 */
459 psxRegs.pc = tar1;
460 tmp1 = psxBranchNoDelay();
461 if (tmp1 == (u32)-1) {
462 return psxDelayBranchExec(tar2);
463 }
464 debugI();
465 psxRegs.cycle += BIAS;
466
467 /*
468 * Got a branch at tar1:
469 * - execute 1 instruction at tar2
470 * - jump to target of that branch (tmp1)
471 */
472 psxRegs.pc = tar2;
473 tmp2 = psxBranchNoDelay();
474 if (tmp2 == (u32)-1) {
475 return psxDelayBranchExec(tmp1);
476 }
477 debugI();
478 psxRegs.cycle += BIAS;
479
480 /*
481 * Got a branch at tar2:
482 * - execute 1 instruction at tmp1
483 * - jump to target of that branch (tmp2)
484 */
485 psxRegs.pc = tmp1;
486 return psxDelayBranchExec(tmp2);
487}
488
4600ba03 489static void doBranch(u32 tar) {
ef79bbde
P
490 u32 *code;
491 u32 tmp;
492
493 branch2 = branch = 1;
494 branchPC = tar;
495
990cb018 496 // check for branch in delay slot
497 if (psxDelayBranchTest(tar))
498 return;
499
943a507a 500 #ifdef ICACHE_EMULATION
501 if (Config.icache_emulation)
502 {
503 code = Read_ICache(psxRegs.pc);
504 }
505 else
506 #endif
507 {
508 code = (u32 *)PSXM(psxRegs.pc);
509 }
ef79bbde
P
510 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
511
512 debugI();
513
514 psxRegs.pc += 4;
515 psxRegs.cycle += BIAS;
516
517 // check for load delay
518 tmp = psxRegs.code >> 26;
519 switch (tmp) {
520 case 0x10: // COP0
521 switch (_Rs_) {
522 case 0x00: // MFC0
523 case 0x02: // CFC0
524 psxDelayTest(_Rt_, branchPC);
525 return;
526 }
527 break;
528 case 0x12: // COP2
529 switch (_Funct_) {
530 case 0x00:
531 switch (_Rs_) {
532 case 0x00: // MFC2
533 case 0x02: // CFC2
534 psxDelayTest(_Rt_, branchPC);
535 return;
536 }
537 break;
538 }
539 break;
540 case 0x32: // LWC2
541 psxDelayTest(_Rt_, branchPC);
542 return;
543 default:
544 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
545 psxDelayTest(_Rt_, branchPC);
546 return;
547 }
548 break;
549 }
550
551 psxBSC[psxRegs.code >> 26]();
552
553 branch = 0;
554 psxRegs.pc = branchPC;
555
556 psxBranchTest();
557}
558
559/*********************************************************
560* Arithmetic with immediate operand *
561* Format: OP rt, rs, immediate *
562*********************************************************/
563void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
564void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
565void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
566void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
567void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
568void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
569void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
570
571/*********************************************************
572* Register arithmetic *
573* Format: OP rd, rs, rt *
574*********************************************************/
575void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
576void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
577void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
578void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
579void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
580void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
581void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
582void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
583void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
584void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
585
586/*********************************************************
587* Register mult/div & Register trap logic *
588* Format: OP rs, rt *
589*********************************************************/
590void psxDIV() {
a4ae3997 591 if (!_i32(_rRt_)) {
592 _i32(_rHi_) = _i32(_rRs_);
593 if (_i32(_rRs_) & 0x80000000) {
594 _i32(_rLo_) = 1;
595 } else {
596 _i32(_rLo_) = 0xFFFFFFFF;
597 }
598/*
599 * Notaz said that this was "not needed" for ARM platforms and could slow it down so let's disable for ARM.
600 * This fixes a crash issue that can happen when running Amidog's CPU test.
601 * (It still stays stuck to a black screen but at least it doesn't crash anymore)
602 */
603#if !defined(__arm__) && !defined(__aarch64__)
604 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
605 _i32(_rLo_) = 0x80000000;
606 _i32(_rHi_) = 0;
607#endif
608 } else {
609 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
610 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
611 }
ef79bbde
P
612}
613
32631e6a 614void psxDIV_stall() {
615 psxRegs.muldivBusyCycle = psxRegs.cycle + 37;
616 psxDIV();
617}
618
ef79bbde
P
619void psxDIVU() {
620 if (_rRt_ != 0) {
621 _rLo_ = _rRs_ / _rRt_;
622 _rHi_ = _rRs_ % _rRt_;
623 }
c7a56f4f 624 else {
625 _i32(_rLo_) = 0xffffffff;
626 _i32(_rHi_) = _i32(_rRs_);
627 }
ef79bbde
P
628}
629
32631e6a 630void psxDIVU_stall() {
631 psxRegs.muldivBusyCycle = psxRegs.cycle + 37;
632 psxDIVU();
633}
634
ef79bbde
P
635void psxMULT() {
636 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
637
638 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
639 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
640}
641
32631e6a 642void psxMULT_stall() {
643 // approximate, but maybe good enough
644 u32 rs = _rRs_;
645 u32 lz = __builtin_clz(((rs ^ ((s32)rs >> 21)) | 1));
646 u32 c = 7 + (2 - (lz / 11)) * 4;
647 psxRegs.muldivBusyCycle = psxRegs.cycle + c;
648 psxMULT();
649}
650
ef79bbde
P
651void psxMULTU() {
652 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
653
654 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
655 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
656}
657
32631e6a 658void psxMULTU_stall() {
659 // approximate, but maybe good enough
660 u32 lz = __builtin_clz(_rRs_ | 1);
661 u32 c = 7 + (2 - (lz / 11)) * 4;
662 psxRegs.muldivBusyCycle = psxRegs.cycle + c;
663 psxMULTU();
664}
665
ef79bbde
P
666/*********************************************************
667* Register branch logic *
668* Format: OP rs, offset *
669*********************************************************/
670#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
943a507a 671#define RepZBranchLinki32(op) { _SetLink(31); if(_i32(_rRs_) op 0) { doBranch(_BranchTarget_); } }
ef79bbde
P
672
673void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
674void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
675void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
676void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
677void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
678void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
679
680/*********************************************************
681* Shift arithmetic with constant shift *
682* Format: OP rd, rt, sa *
683*********************************************************/
684void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
685void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
686void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
687
688/*********************************************************
689* Shift arithmetic with variant register shift *
690* Format: OP rd, rt, rs *
691*********************************************************/
943a507a 692void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << (_u32(_rRs_) & 0x1F); } // Rd = Rt << rs
693void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (arithmetic)
694void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> (_u32(_rRs_) & 0x1F); } // Rd = Rt >> rs (logical)
ef79bbde
P
695
696/*********************************************************
697* Load higher 16 bits of the first word in GPR with imm *
698* Format: OP rt, immediate *
699*********************************************************/
700void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
701
702/*********************************************************
703* Move from HI/LO to GPR *
704* Format: OP rd *
705*********************************************************/
706void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
707void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
708
32631e6a 709static void mflohiCheckStall(void)
710{
711 u32 left = psxRegs.muldivBusyCycle - psxRegs.cycle;
712 if (left <= 37) {
713 //printf("muldiv stall %u\n", left);
714 psxRegs.cycle = psxRegs.muldivBusyCycle;
715 }
716}
717
718void psxMFHI_stall() { mflohiCheckStall(); psxMFHI(); }
719void psxMFLO_stall() { mflohiCheckStall(); psxMFLO(); }
720
ef79bbde
P
721/*********************************************************
722* Move to GPR to HI/LO & Register jump *
723* Format: OP rs *
724*********************************************************/
725void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
726void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
727
728/*********************************************************
729* Special purpose instructions *
730* Format: OP *
731*********************************************************/
732void psxBREAK() {
943a507a 733 psxRegs.pc -= 4;
734 psxException(0x24, branch);
ef79bbde
P
735}
736
737void psxSYSCALL() {
738 psxRegs.pc -= 4;
739 psxException(0x20, branch);
740}
741
742void psxRFE() {
743// SysPrintf("psxRFE\n");
744 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
745 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
943a507a 746 psxTestSWInts();
ef79bbde
P
747}
748
749/*********************************************************
750* Register branch logic *
751* Format: OP rs, rt, offset *
752*********************************************************/
753#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
754
755void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
756void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
757
758/*********************************************************
759* Jump to target *
760* Format: OP target *
761*********************************************************/
762void psxJ() { doBranch(_JumpTarget_); }
763void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
764
765/*********************************************************
766* Register jump *
767* Format: OP rs, rd *
768*********************************************************/
769void psxJR() {
943a507a 770 doBranch(_rRs_ & ~3);
ef79bbde
P
771 psxJumpTest();
772}
773
774void psxJALR() {
775 u32 temp = _u32(_rRs_);
776 if (_Rd_) { _SetLink(_Rd_); }
943a507a 777 doBranch(temp & ~3);
ef79bbde
P
778}
779
780/*********************************************************
781* Load and store for GPR *
782* Format: OP rt, offset(base) *
783*********************************************************/
784
785#define _oB_ (_u32(_rRs_) + _Imm_)
786
787void psxLB() {
788 if (_Rt_) {
789 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
790 } else {
791 psxMemRead8(_oB_);
792 }
793}
794
795void psxLBU() {
796 if (_Rt_) {
797 _u32(_rRt_) = psxMemRead8(_oB_);
798 } else {
799 psxMemRead8(_oB_);
800 }
801}
802
803void psxLH() {
804 if (_Rt_) {
805 _i32(_rRt_) = (short)psxMemRead16(_oB_);
806 } else {
807 psxMemRead16(_oB_);
808 }
809}
810
811void psxLHU() {
812 if (_Rt_) {
813 _u32(_rRt_) = psxMemRead16(_oB_);
814 } else {
815 psxMemRead16(_oB_);
816 }
817}
818
819void psxLW() {
820 if (_Rt_) {
821 _u32(_rRt_) = psxMemRead32(_oB_);
822 } else {
823 psxMemRead32(_oB_);
824 }
825}
826
827u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
828u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
829
830void psxLWL() {
831 u32 addr = _oB_;
832 u32 shift = addr & 3;
833 u32 mem = psxMemRead32(addr & ~3);
834
835 if (!_Rt_) return;
836 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
837 ( mem << LWL_SHIFT[shift]);
838
839 /*
840 Mem = 1234. Reg = abcd
841
842 0 4bcd (mem << 24) | (reg & 0x00ffffff)
843 1 34cd (mem << 16) | (reg & 0x0000ffff)
844 2 234d (mem << 8) | (reg & 0x000000ff)
845 3 1234 (mem ) | (reg & 0x00000000)
846 */
847}
848
849u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
850u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
851
852void psxLWR() {
853 u32 addr = _oB_;
854 u32 shift = addr & 3;
855 u32 mem = psxMemRead32(addr & ~3);
856
857 if (!_Rt_) return;
858 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
859 ( mem >> LWR_SHIFT[shift]);
860
861 /*
862 Mem = 1234. Reg = abcd
863
864 0 1234 (mem ) | (reg & 0x00000000)
865 1 a123 (mem >> 8) | (reg & 0xff000000)
866 2 ab12 (mem >> 16) | (reg & 0xffff0000)
867 3 abc1 (mem >> 24) | (reg & 0xffffff00)
868 */
869}
870
b1ba0851 871void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
872void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
873void psxSW() { psxMemWrite32(_oB_, _rRt_); }
ef79bbde
P
874
875u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
876u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
877
878void psxSWL() {
879 u32 addr = _oB_;
880 u32 shift = addr & 3;
881 u32 mem = psxMemRead32(addr & ~3);
882
883 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
884 ( mem & SWL_MASK[shift]) );
885 /*
886 Mem = 1234. Reg = abcd
887
888 0 123a (reg >> 24) | (mem & 0xffffff00)
889 1 12ab (reg >> 16) | (mem & 0xffff0000)
890 2 1abc (reg >> 8) | (mem & 0xff000000)
891 3 abcd (reg ) | (mem & 0x00000000)
892 */
893}
894
895u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
896u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
897
898void psxSWR() {
899 u32 addr = _oB_;
900 u32 shift = addr & 3;
901 u32 mem = psxMemRead32(addr & ~3);
902
903 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
904 ( mem & SWR_MASK[shift]) );
905
906 /*
907 Mem = 1234. Reg = abcd
908
909 0 abcd (reg ) | (mem & 0x00000000)
910 1 bcd4 (reg << 8) | (mem & 0x000000ff)
911 2 cd34 (reg << 16) | (mem & 0x0000ffff)
912 3 d234 (reg << 24) | (mem & 0x00ffffff)
913 */
914}
915
916/*********************************************************
917* Moves between GPR and COPx *
918* Format: OP rt, fs *
919*********************************************************/
920void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
921void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
922
923void psxTestSWInts() {
ef79bbde 924 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
48e74ef5 925 psxRegs.CP0.n.Status & 0x1) {
926 psxRegs.CP0.n.Cause &= ~0x7c;
ef79bbde
P
927 psxException(psxRegs.CP0.n.Cause, branch);
928 }
929}
930
4600ba03 931void MTC0(int reg, u32 val) {
ef79bbde
P
932// SysPrintf("MTC0 %d: %x\n", reg, val);
933 switch (reg) {
934 case 12: // Status
935 psxRegs.CP0.r[12] = val;
936 psxTestSWInts();
937 break;
938
939 case 13: // Cause
48e74ef5 940 psxRegs.CP0.n.Cause &= ~0x0300;
941 psxRegs.CP0.n.Cause |= val & 0x0300;
ef79bbde
P
942 psxTestSWInts();
943 break;
944
945 default:
946 psxRegs.CP0.r[reg] = val;
947 break;
948 }
949}
950
951void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
952void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
953
954/*********************************************************
955* Unknow instruction (would generate an exception) *
956* Format: ? *
957*********************************************************/
958void psxNULL() {
959#ifdef PSXCPU_LOG
960 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
961#endif
962}
963
964void psxSPECIAL() {
965 psxSPC[_Funct_]();
966}
967
968void psxREGIMM() {
969 psxREG[_Rt_]();
970}
971
972void psxCOP0() {
973 psxCP0[_Rs_]();
974}
975
976void psxCOP2() {
32631e6a 977 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
978}
979
980void psxCOP2_stall() {
81dbbf4c 981 u32 f = _Funct_;
32631e6a 982 gteCheckStall(f);
81dbbf4c 983 psxCP2[f]((struct psxCP2Regs *)&psxRegs.CP2D);
ef79bbde
P
984}
985
6c0eefaf 986void psxBASIC(struct psxCP2Regs *regs) {
ef79bbde
P
987 psxCP2BSC[_Rs_]();
988}
989
990void psxHLE() {
991// psxHLEt[psxRegs.code & 0xffff]();
dd79da89 992// psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
993 uint32_t hleCode = psxRegs.code & 0x03ffffff;
994 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
995 psxNULL();
996 } else {
997 psxHLEt[hleCode]();
998 }
ef79bbde
P
999}
1000
1001void (*psxBSC[64])() = {
1002 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
1003 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
1004 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1005 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1006 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
1007 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
1008 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
1009 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
1010};
1011
1012
1013void (*psxSPC[64])() = {
1014 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
1015 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
1016 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
1017 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
1018 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
1019 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
1020 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
1021 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
1022};
1023
1024void (*psxREG[32])() = {
1025 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1026 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1027 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1028 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1029};
1030
1031void (*psxCP0[32])() = {
1032 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
1033 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1034 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1035 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1036};
1037
6c0eefaf 1038void (*psxCP2[64])(struct psxCP2Regs *regs) = {
ef79bbde
P
1039 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
1040 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
1041 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
1042 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
1043 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
1044 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
1045 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
1046 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
1047};
1048
1049void (*psxCP2BSC[32])() = {
1050 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
1051 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1052 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
1053 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
1054};
1055
1056
1057///////////////////////////////////////////
1058
1059static int intInit() {
943a507a 1060 #ifdef ICACHE_EMULATION
1061 /* We have to allocate the icache memory even if
1062 * the user has not enabled it as otherwise it can cause issues.
1063 */
1064 if (!ICache_Addr)
1065 {
1066 ICache_Addr = malloc(0x1000);
1067 if (!ICache_Addr)
1068 {
1069 return -1;
1070 }
1071 }
1072
1073 if (!ICache_Code)
1074 {
1075 ICache_Code = malloc(0x1000);
1076 if (!ICache_Code)
1077 {
1078 return -1;
1079 }
1080 }
1081 memset(ICache_Addr, 0xff, 0x1000);
1082 memset(ICache_Code, 0xff, 0x1000);
1083 #endif
ef79bbde
P
1084 return 0;
1085}
1086
1087static void intReset() {
943a507a 1088 #ifdef ICACHE_EMULATION
1089 memset(ICache_Addr, 0xff, 0x1000);
1090 memset(ICache_Code, 0xff, 0x1000);
1091 #endif
ef79bbde
P
1092}
1093
796a91ef 1094void intExecute() {
1095 extern int stop;
1096 for (;!stop;)
ef79bbde
P
1097 execI();
1098}
1099
796a91ef 1100void intExecuteBlock() {
ef79bbde
P
1101 branch2 = 0;
1102 while (!branch2) execI();
1103}
1104
1105static void intClear(u32 Addr, u32 Size) {
1106}
1107
943a507a 1108void intNotify (int note, void *data) {
1109 #ifdef ICACHE_EMULATION
1110 /* Gameblabla - Only clear the icache if it's isolated */
1111 if (note == R3000ACPU_NOTIFY_CACHE_ISOLATED)
1112 {
1113 memset(ICache_Addr, 0xff, 0x1000);
1114 memset(ICache_Code, 0xff, 0x1000);
1115 }
1116 #endif
1117}
1118
32631e6a 1119void applyConfig() {
1120 assert(psxBSC[18] == psxCOP2 || psxBSC[18] == psxCOP2_stall);
1121 assert(psxBSC[50] == gteLWC2 || psxBSC[50] == gteLWC2_stall);
1122 assert(psxBSC[58] == gteSWC2 || psxBSC[58] == gteSWC2_stall);
1123 assert(psxSPC[16] == psxMFHI || psxSPC[16] == psxMFHI_stall);
1124 assert(psxSPC[18] == psxMFLO || psxSPC[18] == psxMFLO_stall);
1125 assert(psxSPC[24] == psxMULT || psxSPC[24] == psxMULT_stall);
1126 assert(psxSPC[25] == psxMULTU || psxSPC[25] == psxMULTU_stall);
1127 assert(psxSPC[26] == psxDIV || psxSPC[26] == psxDIV_stall);
1128 assert(psxSPC[27] == psxDIVU || psxSPC[27] == psxDIVU_stall);
1129
1130 if (Config.DisableStalls) {
1131 psxBSC[18] = psxCOP2;
1132 psxBSC[50] = gteLWC2;
1133 psxBSC[58] = gteSWC2;
1134 psxSPC[16] = psxMFHI;
1135 psxSPC[18] = psxMFLO;
1136 psxSPC[24] = psxMULT;
1137 psxSPC[25] = psxMULTU;
1138 psxSPC[26] = psxDIV;
1139 psxSPC[27] = psxDIVU;
1140 } else {
1141 psxBSC[18] = psxCOP2_stall;
1142 psxBSC[50] = gteLWC2_stall;
1143 psxBSC[58] = gteSWC2_stall;
1144 psxSPC[16] = psxMFHI_stall;
1145 psxSPC[18] = psxMFLO_stall;
1146 psxSPC[24] = psxMULT_stall;
1147 psxSPC[25] = psxMULTU_stall;
1148 psxSPC[26] = psxDIV_stall;
1149 psxSPC[27] = psxDIVU_stall;
1150 }
1151}
1152
ef79bbde 1153static void intShutdown() {
943a507a 1154 #ifdef ICACHE_EMULATION
1155 if (ICache_Addr)
1156 {
1157 free(ICache_Addr);
1158 ICache_Addr = NULL;
1159 }
1160
1161 if (ICache_Code)
1162 {
1163 free(ICache_Code);
1164 ICache_Code = NULL;
1165 }
1166 #endif
ef79bbde
P
1167}
1168
1169// interpreter execution
4600ba03 1170void execI() {
943a507a 1171 u32 *code;
1172 #ifdef ICACHE_EMULATION
1173 if (Config.icache_emulation)
1174 {
1175 code = Read_ICache(psxRegs.pc);
1176 }
1177 else
1178 #endif
1179 {
1180 code = (u32 *)PSXM(psxRegs.pc);
1181 }
ef79bbde
P
1182 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
1183
1184 debugI();
1185
1186 if (Config.Debug) ProcessDebug();
1187
1188 psxRegs.pc += 4;
1189 psxRegs.cycle += BIAS;
1190
1191 psxBSC[psxRegs.code >> 26]();
1192}
1193
1194R3000Acpu psxInt = {
1195 intInit,
1196 intReset,
1197 intExecute,
1198 intExecuteBlock,
1199 intClear,
943a507a 1200#ifdef ICACHE_EMULATION
1201 intNotify,
1202#endif
32631e6a 1203 applyConfig,
ef79bbde
P
1204 intShutdown
1205};