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_);
508 _i32(_rLo_) = _i32(_rRs_) >= 0 ? 0xffffffff : 1;
509 _i32(_rHi_) = _i32(_rRs_);
515 _rLo_ = _rRs_ / _rRt_;
516 _rHi_ = _rRs_ % _rRt_;
519 _i32(_rLo_) = 0xffffffff;
520 _i32(_rHi_) = _i32(_rRs_);
525 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
527 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
528 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
532 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
534 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
535 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
538 /*********************************************************
539 * Register branch logic *
540 * Format: OP rs, offset *
541 *********************************************************/
542 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
543 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
545 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
546 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
547 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
548 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
549 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
550 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
552 /*********************************************************
553 * Shift arithmetic with constant shift *
554 * Format: OP rd, rt, sa *
555 *********************************************************/
556 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
557 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
558 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
560 /*********************************************************
561 * Shift arithmetic with variant register shift *
562 * Format: OP rd, rt, rs *
563 *********************************************************/
564 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
565 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
566 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
568 /*********************************************************
569 * Load higher 16 bits of the first word in GPR with imm *
570 * Format: OP rt, immediate *
571 *********************************************************/
572 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
574 /*********************************************************
575 * Move from HI/LO to GPR *
577 *********************************************************/
578 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
579 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
581 /*********************************************************
582 * Move to GPR to HI/LO & Register jump *
584 *********************************************************/
585 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
586 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
588 /*********************************************************
589 * Special purpose instructions *
591 *********************************************************/
593 // Break exception - psx rom doens't handles this
598 psxException(0x20, branch);
602 // SysPrintf("psxRFE\n");
603 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
604 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
607 /*********************************************************
608 * Register branch logic *
609 * Format: OP rs, rt, offset *
610 *********************************************************/
611 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
613 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
614 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
616 /*********************************************************
618 * Format: OP target *
619 *********************************************************/
620 void psxJ() { doBranch(_JumpTarget_); }
621 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
623 /*********************************************************
625 * Format: OP rs, rd *
626 *********************************************************/
628 doBranch(_u32(_rRs_));
633 u32 temp = _u32(_rRs_);
634 if (_Rd_) { _SetLink(_Rd_); }
638 /*********************************************************
639 * Load and store for GPR *
640 * Format: OP rt, offset(base) *
641 *********************************************************/
643 #define _oB_ (_u32(_rRs_) + _Imm_)
647 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
655 _u32(_rRt_) = psxMemRead8(_oB_);
663 _i32(_rRt_) = (short)psxMemRead16(_oB_);
671 _u32(_rRt_) = psxMemRead16(_oB_);
679 _u32(_rRt_) = psxMemRead32(_oB_);
685 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
686 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
690 u32 shift = addr & 3;
691 u32 mem = psxMemRead32(addr & ~3);
694 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
695 ( mem << LWL_SHIFT[shift]);
698 Mem = 1234. Reg = abcd
700 0 4bcd (mem << 24) | (reg & 0x00ffffff)
701 1 34cd (mem << 16) | (reg & 0x0000ffff)
702 2 234d (mem << 8) | (reg & 0x000000ff)
703 3 1234 (mem ) | (reg & 0x00000000)
707 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
708 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
712 u32 shift = addr & 3;
713 u32 mem = psxMemRead32(addr & ~3);
716 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
717 ( mem >> LWR_SHIFT[shift]);
720 Mem = 1234. Reg = abcd
722 0 1234 (mem ) | (reg & 0x00000000)
723 1 a123 (mem >> 8) | (reg & 0xff000000)
724 2 ab12 (mem >> 16) | (reg & 0xffff0000)
725 3 abc1 (mem >> 24) | (reg & 0xffffff00)
729 void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
730 void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
731 void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
733 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
734 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
738 u32 shift = addr & 3;
739 u32 mem = psxMemRead32(addr & ~3);
741 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
742 ( mem & SWL_MASK[shift]) );
744 Mem = 1234. Reg = abcd
746 0 123a (reg >> 24) | (mem & 0xffffff00)
747 1 12ab (reg >> 16) | (mem & 0xffff0000)
748 2 1abc (reg >> 8) | (mem & 0xff000000)
749 3 abcd (reg ) | (mem & 0x00000000)
753 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
754 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
758 u32 shift = addr & 3;
759 u32 mem = psxMemRead32(addr & ~3);
761 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
762 ( mem & SWR_MASK[shift]) );
765 Mem = 1234. Reg = abcd
767 0 abcd (reg ) | (mem & 0x00000000)
768 1 bcd4 (reg << 8) | (mem & 0x000000ff)
769 2 cd34 (reg << 16) | (mem & 0x0000ffff)
770 3 d234 (reg << 24) | (mem & 0x00ffffff)
774 /*********************************************************
775 * Moves between GPR and COPx *
776 * Format: OP rt, fs *
777 *********************************************************/
778 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
779 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
781 void psxTestSWInts() {
782 // the next code is untested, if u know please
783 // tell me if it works ok or not (linuzappz)
784 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
785 psxRegs.CP0.n.Status & 0x1) {
786 psxException(psxRegs.CP0.n.Cause, branch);
790 __inline void MTC0(int reg, u32 val) {
791 // SysPrintf("MTC0 %d: %x\n", reg, val);
794 psxRegs.CP0.r[12] = val;
799 psxRegs.CP0.n.Cause = val & ~(0xfc00);
804 psxRegs.CP0.r[reg] = val;
809 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
810 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
812 /*********************************************************
813 * Unknow instruction (would generate an exception) *
815 *********************************************************/
818 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
843 // psxHLEt[psxRegs.code & 0xffff]();
844 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
847 void (*psxBSC[64])() = {
848 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
849 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
850 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
851 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
852 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
853 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
854 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
855 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
859 void (*psxSPC[64])() = {
860 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
861 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
862 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
863 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
864 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
865 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
866 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
867 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
870 void (*psxREG[32])() = {
871 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
872 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
873 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
874 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
877 void (*psxCP0[32])() = {
878 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
879 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
880 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
881 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
884 void (*psxCP2[64])() = {
885 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
886 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
887 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
888 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
889 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
890 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
891 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
892 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
895 void (*psxCP2BSC[32])() = {
896 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
897 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
898 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
899 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
903 ///////////////////////////////////////////
905 static int intInit() {
909 static void intReset() {
918 void intExecuteBlock() {
920 while (!branch2) execI();
923 static void intClear(u32 Addr, u32 Size) {
926 static void intShutdown() {
929 // interpreter execution
930 inline void execI() {
931 u32 *code = (u32 *)PSXM(psxRegs.pc);
932 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
936 if (Config.Debug) ProcessDebug();
939 psxRegs.cycle += BIAS;
941 psxBSC[psxRegs.code >> 26]();