1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
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. *
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. *
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 ***************************************************************************/
21 * PSX assembly interpreter.
24 #include "psxcommon.h"
29 static int branch = 0;
30 static int branch2 = 0;
33 // These macros are used to assemble the repassembler functions
36 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
49 void (*psxCP2BSC[32])();
51 static void delayRead(int reg, u32 bpc) {
54 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
56 rold = psxRegs.GPR.r[reg];
57 psxBSC[psxRegs.code >> 26](); // branch delay load
58 rnew = psxRegs.GPR.r[reg];
64 psxRegs.GPR.r[reg] = rold;
65 execI(); // first branch opcode
66 psxRegs.GPR.r[reg] = rnew;
71 static void delayWrite(int reg, u32 bpc) {
73 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
75 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
76 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
78 // no changes from normal behavior
80 psxBSC[psxRegs.code >> 26]();
88 static void delayReadWrite(int reg, u32 bpc) {
90 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
92 // the branch delay load is skipped
100 // this defines shall be used with the tmp
101 // of the next func (instead of _Funct_...)
102 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
103 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
104 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
105 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
106 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
108 int psxTestLoadDelay(int reg, u32 tmp) {
109 if (tmp == 0) return 0; // NOP
111 case 0x00: // SPECIAL
114 case 0x02: case 0x03: // SRL/SRA
115 if (_tRd_ == reg && _tRt_ == reg) return 1; else
116 if (_tRt_ == reg) return 2; else
117 if (_tRd_ == reg) return 3;
121 if (_tRs_ == reg) return 2;
124 if (_tRd_ == reg && _tRs_ == reg) return 1; else
125 if (_tRs_ == reg) return 2; else
126 if (_tRd_ == reg) return 3;
129 // SYSCALL/BREAK just a break;
131 case 0x20: case 0x21: case 0x22: case 0x23:
132 case 0x24: case 0x25: case 0x26: case 0x27:
133 case 0x2a: case 0x2b: // ADD/ADDU...
134 case 0x04: case 0x06: case 0x07: // SLLV...
135 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
136 if (_tRt_ == reg || _tRs_ == reg) return 2; else
137 if (_tRd_ == reg) return 3;
140 case 0x10: case 0x12: // MFHI/MFLO
141 if (_tRd_ == reg) return 3;
143 case 0x11: case 0x13: // MTHI/MTLO
144 if (_tRs_ == reg) return 2;
147 case 0x18: case 0x19:
148 case 0x1a: case 0x1b: // MULT/DIV...
149 if (_tRt_ == reg || _tRs_ == reg) return 2;
156 case 0x00: case 0x01:
157 case 0x10: case 0x11: // BLTZ/BGEZ...
158 // Xenogears - lbu v0 / beq v0
159 // - no load delay (fixes battle loading)
162 if (_tRs_ == reg) return 2;
167 // J would be just a break;
169 if (31 == reg) return 3;
172 case 0x04: case 0x05: // BEQ/BNE
173 // Xenogears - lbu v0 / beq v0
174 // - no load delay (fixes battle loading)
177 if (_tRs_ == reg || _tRt_ == reg) return 2;
180 case 0x06: case 0x07: // BLEZ/BGTZ
181 // Xenogears - lbu v0 / beq v0
182 // - no load delay (fixes battle loading)
185 if (_tRs_ == reg) return 2;
188 case 0x08: case 0x09: case 0x0a: case 0x0b:
189 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
190 if (_tRt_ == reg && _tRs_ == reg) return 1; else
191 if (_tRs_ == reg) return 2; else
192 if (_tRt_ == reg) return 3;
196 if (_tRt_ == reg) return 3;
202 if (_tRt_ == reg) return 3;
205 if (_tRt_ == reg) return 3;
208 if (_tRt_ == reg) return 2;
211 if (_tRt_ == reg) return 2;
222 if (_tRt_ == reg) return 3;
225 if (_tRt_ == reg) return 3;
228 if (_tRt_ == reg) return 2;
231 if (_tRt_ == reg) return 2;
239 case 0x22: case 0x26: // LWL/LWR
240 if (_tRt_ == reg) return 3; else
241 if (_tRs_ == reg) return 2;
244 case 0x20: case 0x21: case 0x23:
245 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
246 if (_tRt_ == reg && _tRs_ == reg) return 1; else
247 if (_tRs_ == reg) return 2; else
248 if (_tRt_ == reg) return 3;
251 case 0x28: case 0x29: case 0x2a:
252 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
253 if (_tRt_ == reg || _tRs_ == reg) return 2;
256 case 0x32: case 0x3a: // LWC2/SWC2
257 if (_tRs_ == reg) return 2;
264 void psxDelayTest(int reg, u32 bpc) {
268 code = (u32 *)PSXM(bpc);
269 tmp = ((code == NULL) ? 0 : SWAP32(*code));
272 switch (psxTestLoadDelay(reg, tmp)) {
274 delayReadWrite(reg, bpc); return;
276 delayRead(reg, bpc); return;
278 delayWrite(reg, bpc); return;
280 psxBSC[psxRegs.code >> 26]();
288 static u32 psxBranchNoDelay(void) {
292 code = (u32 *)PSXM(psxRegs.pc);
293 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
295 case 0x00: // SPECIAL
301 if (_Rd_) { _SetLink(_Rd_); }
309 return _BranchTarget_;
312 if (_i32(_rRs_) >= 0)
313 return _BranchTarget_;
316 if (_i32(_rRs_) < 0) {
318 return _BranchTarget_;
322 if (_i32(_rRs_) >= 0) {
324 return _BranchTarget_;
335 if (_i32(_rRs_) == _i32(_rRt_))
336 return _BranchTarget_;
339 if (_i32(_rRs_) != _i32(_rRt_))
340 return _BranchTarget_;
343 if (_i32(_rRs_) <= 0)
344 return _BranchTarget_;
348 return _BranchTarget_;
355 static int psxDelayBranchExec(u32 tar) {
360 psxRegs.cycle += BIAS;
365 static int psxDelayBranchTest(u32 tar1) {
366 u32 tar2, tmp1, tmp2;
368 tar2 = psxBranchNoDelay();
375 * Branch in delay slot:
376 * - execute 1 instruction at tar1
377 * - jump to tar2 (target of branch in delay slot; this branch
378 * has no normal delay slot, instruction at tar1 was fetched instead)
381 tmp1 = psxBranchNoDelay();
382 if (tmp1 == (u32)-1) {
383 return psxDelayBranchExec(tar2);
386 psxRegs.cycle += BIAS;
389 * Got a branch at tar1:
390 * - execute 1 instruction at tar2
391 * - jump to target of that branch (tmp1)
394 tmp2 = psxBranchNoDelay();
395 if (tmp2 == (u32)-1) {
396 return psxDelayBranchExec(tmp1);
399 psxRegs.cycle += BIAS;
402 * Got a branch at tar2:
403 * - execute 1 instruction at tmp1
404 * - jump to target of that branch (tmp2)
407 return psxDelayBranchExec(tmp2);
410 __inline void doBranch(u32 tar) {
414 branch2 = branch = 1;
417 // check for branch in delay slot
418 if (psxDelayBranchTest(tar))
421 code = (u32 *)PSXM(psxRegs.pc);
422 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
427 psxRegs.cycle += BIAS;
429 // check for load delay
430 tmp = psxRegs.code >> 26;
436 psxDelayTest(_Rt_, branchPC);
446 psxDelayTest(_Rt_, branchPC);
453 psxDelayTest(_Rt_, branchPC);
456 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
457 psxDelayTest(_Rt_, branchPC);
463 psxBSC[psxRegs.code >> 26]();
466 psxRegs.pc = branchPC;
471 /*********************************************************
472 * Arithmetic with immediate operand *
473 * Format: OP rt, rs, immediate *
474 *********************************************************/
475 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
476 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
477 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
478 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
479 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
480 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
481 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
483 /*********************************************************
484 * Register arithmetic *
485 * Format: OP rd, rs, rt *
486 *********************************************************/
487 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
488 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
489 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
490 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
491 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
492 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
493 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
494 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
495 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
496 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
498 /*********************************************************
499 * Register mult/div & Register trap logic *
500 * Format: OP rs, rt *
501 *********************************************************/
503 if (_i32(_rRt_) != 0) {
504 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
505 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
511 _rLo_ = _rRs_ / _rRt_;
512 _rHi_ = _rRs_ % _rRt_;
517 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
519 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
520 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
524 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
526 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
527 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
530 /*********************************************************
531 * Register branch logic *
532 * Format: OP rs, offset *
533 *********************************************************/
534 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
535 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
537 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
538 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
539 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
540 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
541 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
542 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
544 /*********************************************************
545 * Shift arithmetic with constant shift *
546 * Format: OP rd, rt, sa *
547 *********************************************************/
548 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
549 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
550 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
552 /*********************************************************
553 * Shift arithmetic with variant register shift *
554 * Format: OP rd, rt, rs *
555 *********************************************************/
556 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
557 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
558 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
560 /*********************************************************
561 * Load higher 16 bits of the first word in GPR with imm *
562 * Format: OP rt, immediate *
563 *********************************************************/
564 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
566 /*********************************************************
567 * Move from HI/LO to GPR *
569 *********************************************************/
570 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
571 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
573 /*********************************************************
574 * Move to GPR to HI/LO & Register jump *
576 *********************************************************/
577 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
578 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
580 /*********************************************************
581 * Special purpose instructions *
583 *********************************************************/
585 // Break exception - psx rom doens't handles this
590 psxException(0x20, branch);
594 // SysPrintf("psxRFE\n");
595 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
596 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
599 /*********************************************************
600 * Register branch logic *
601 * Format: OP rs, rt, offset *
602 *********************************************************/
603 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
605 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
606 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
608 /*********************************************************
610 * Format: OP target *
611 *********************************************************/
612 void psxJ() { doBranch(_JumpTarget_); }
613 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
615 /*********************************************************
617 * Format: OP rs, rd *
618 *********************************************************/
620 doBranch(_u32(_rRs_));
625 u32 temp = _u32(_rRs_);
626 if (_Rd_) { _SetLink(_Rd_); }
630 /*********************************************************
631 * Load and store for GPR *
632 * Format: OP rt, offset(base) *
633 *********************************************************/
635 #define _oB_ (_u32(_rRs_) + _Imm_)
639 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
647 _u32(_rRt_) = psxMemRead8(_oB_);
655 _i32(_rRt_) = (short)psxMemRead16(_oB_);
663 _u32(_rRt_) = psxMemRead16(_oB_);
671 _u32(_rRt_) = psxMemRead32(_oB_);
677 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
678 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
682 u32 shift = addr & 3;
683 u32 mem = psxMemRead32(addr & ~3);
686 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
687 ( mem << LWL_SHIFT[shift]);
690 Mem = 1234. Reg = abcd
692 0 4bcd (mem << 24) | (reg & 0x00ffffff)
693 1 34cd (mem << 16) | (reg & 0x0000ffff)
694 2 234d (mem << 8) | (reg & 0x000000ff)
695 3 1234 (mem ) | (reg & 0x00000000)
699 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
700 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
704 u32 shift = addr & 3;
705 u32 mem = psxMemRead32(addr & ~3);
708 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
709 ( mem >> LWR_SHIFT[shift]);
712 Mem = 1234. Reg = abcd
714 0 1234 (mem ) | (reg & 0x00000000)
715 1 a123 (mem >> 8) | (reg & 0xff000000)
716 2 ab12 (mem >> 16) | (reg & 0xffff0000)
717 3 abc1 (mem >> 24) | (reg & 0xffffff00)
721 void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
722 void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
723 void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
725 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
726 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
730 u32 shift = addr & 3;
731 u32 mem = psxMemRead32(addr & ~3);
733 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
734 ( mem & SWL_MASK[shift]) );
736 Mem = 1234. Reg = abcd
738 0 123a (reg >> 24) | (mem & 0xffffff00)
739 1 12ab (reg >> 16) | (mem & 0xffff0000)
740 2 1abc (reg >> 8) | (mem & 0xff000000)
741 3 abcd (reg ) | (mem & 0x00000000)
745 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
746 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
750 u32 shift = addr & 3;
751 u32 mem = psxMemRead32(addr & ~3);
753 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
754 ( mem & SWR_MASK[shift]) );
757 Mem = 1234. Reg = abcd
759 0 abcd (reg ) | (mem & 0x00000000)
760 1 bcd4 (reg << 8) | (mem & 0x000000ff)
761 2 cd34 (reg << 16) | (mem & 0x0000ffff)
762 3 d234 (reg << 24) | (mem & 0x00ffffff)
766 /*********************************************************
767 * Moves between GPR and COPx *
768 * Format: OP rt, fs *
769 *********************************************************/
770 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
771 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
773 void psxTestSWInts() {
774 // the next code is untested, if u know please
775 // tell me if it works ok or not (linuzappz)
776 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
777 psxRegs.CP0.n.Status & 0x1) {
778 psxException(psxRegs.CP0.n.Cause, branch);
782 __inline void MTC0(int reg, u32 val) {
783 // SysPrintf("MTC0 %d: %x\n", reg, val);
786 psxRegs.CP0.r[12] = val;
791 psxRegs.CP0.n.Cause = val & ~(0xfc00);
796 psxRegs.CP0.r[reg] = val;
801 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
802 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
804 /*********************************************************
805 * Unknow instruction (would generate an exception) *
807 *********************************************************/
810 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
835 // psxHLEt[psxRegs.code & 0xffff]();
836 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
839 void (*psxBSC[64])() = {
840 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
841 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
842 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
843 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
844 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
845 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
846 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
847 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
851 void (*psxSPC[64])() = {
852 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
853 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
854 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
855 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
856 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
857 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
858 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
859 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
862 void (*psxREG[32])() = {
863 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
864 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
865 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
866 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
869 void (*psxCP0[32])() = {
870 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
871 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
872 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
873 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
876 void (*psxCP2[64])() = {
877 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
878 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
879 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
880 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
881 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
882 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
883 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
884 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
887 void (*psxCP2BSC[32])() = {
888 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
889 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
890 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
891 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
895 ///////////////////////////////////////////
897 static int intInit() {
901 static void intReset() {
910 void intExecuteBlock() {
912 while (!branch2) execI();
915 static void intClear(u32 Addr, u32 Size) {
918 static void intShutdown() {
921 // interpreter execution
922 inline void execI() {
923 u32 *code = (u32 *)PSXM(psxRegs.pc);
924 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
928 if (Config.Debug) ProcessDebug();
931 psxRegs.cycle += BIAS;
933 psxBSC[psxRegs.code >> 26]();