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"
30 static int branch = 0;
31 static int branch2 = 0;
34 // These macros are used to assemble the repassembler functions
37 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
49 void (*psxCP2[64])(struct psxCP2Regs *regs);
50 void (*psxCP2BSC[32])();
52 static void delayRead(int reg, u32 bpc) {
55 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
57 rold = psxRegs.GPR.r[reg];
58 psxBSC[psxRegs.code >> 26](); // branch delay load
59 rnew = psxRegs.GPR.r[reg];
65 psxRegs.GPR.r[reg] = rold;
66 execI(); // first branch opcode
67 psxRegs.GPR.r[reg] = rnew;
72 static void delayWrite(int reg, u32 bpc) {
74 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
76 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
77 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
79 // no changes from normal behavior
81 psxBSC[psxRegs.code >> 26]();
89 static void delayReadWrite(int reg, u32 bpc) {
91 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
93 // the branch delay load is skipped
101 // this defines shall be used with the tmp
102 // of the next func (instead of _Funct_...)
103 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
104 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
105 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
106 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
107 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
109 int psxTestLoadDelay(int reg, u32 tmp) {
110 if (tmp == 0) return 0; // NOP
112 case 0x00: // SPECIAL
115 case 0x02: case 0x03: // SRL/SRA
116 if (_tRd_ == reg && _tRt_ == reg) return 1; else
117 if (_tRt_ == reg) return 2; else
118 if (_tRd_ == reg) return 3;
122 if (_tRs_ == reg) return 2;
125 if (_tRd_ == reg && _tRs_ == reg) return 1; else
126 if (_tRs_ == reg) return 2; else
127 if (_tRd_ == reg) return 3;
130 // SYSCALL/BREAK just a break;
132 case 0x20: case 0x21: case 0x22: case 0x23:
133 case 0x24: case 0x25: case 0x26: case 0x27:
134 case 0x2a: case 0x2b: // ADD/ADDU...
135 case 0x04: case 0x06: case 0x07: // SLLV...
136 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
137 if (_tRt_ == reg || _tRs_ == reg) return 2; else
138 if (_tRd_ == reg) return 3;
141 case 0x10: case 0x12: // MFHI/MFLO
142 if (_tRd_ == reg) return 3;
144 case 0x11: case 0x13: // MTHI/MTLO
145 if (_tRs_ == reg) return 2;
148 case 0x18: case 0x19:
149 case 0x1a: case 0x1b: // MULT/DIV...
150 if (_tRt_ == reg || _tRs_ == reg) return 2;
157 case 0x00: case 0x01:
158 case 0x10: case 0x11: // BLTZ/BGEZ...
159 // Xenogears - lbu v0 / beq v0
160 // - no load delay (fixes battle loading)
163 if (_tRs_ == reg) return 2;
168 // J would be just a break;
170 if (31 == reg) return 3;
173 case 0x04: case 0x05: // BEQ/BNE
174 // Xenogears - lbu v0 / beq v0
175 // - no load delay (fixes battle loading)
178 if (_tRs_ == reg || _tRt_ == reg) return 2;
181 case 0x06: case 0x07: // BLEZ/BGTZ
182 // Xenogears - lbu v0 / beq v0
183 // - no load delay (fixes battle loading)
186 if (_tRs_ == reg) return 2;
189 case 0x08: case 0x09: case 0x0a: case 0x0b:
190 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
191 if (_tRt_ == reg && _tRs_ == reg) return 1; else
192 if (_tRs_ == reg) return 2; else
193 if (_tRt_ == reg) return 3;
197 if (_tRt_ == reg) return 3;
203 if (_tRt_ == reg) return 3;
206 if (_tRt_ == reg) return 3;
209 if (_tRt_ == reg) return 2;
212 if (_tRt_ == reg) return 2;
223 if (_tRt_ == reg) return 3;
226 if (_tRt_ == reg) return 3;
229 if (_tRt_ == reg) return 2;
232 if (_tRt_ == reg) return 2;
240 case 0x22: case 0x26: // LWL/LWR
241 if (_tRt_ == reg) return 3; else
242 if (_tRs_ == reg) return 2;
245 case 0x20: case 0x21: case 0x23:
246 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
247 if (_tRt_ == reg && _tRs_ == reg) return 1; else
248 if (_tRs_ == reg) return 2; else
249 if (_tRt_ == reg) return 3;
252 case 0x28: case 0x29: case 0x2a:
253 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
254 if (_tRt_ == reg || _tRs_ == reg) return 2;
257 case 0x32: case 0x3a: // LWC2/SWC2
258 if (_tRs_ == reg) return 2;
265 void psxDelayTest(int reg, u32 bpc) {
269 code = (u32 *)PSXM(bpc);
270 tmp = ((code == NULL) ? 0 : SWAP32(*code));
273 switch (psxTestLoadDelay(reg, tmp)) {
275 delayReadWrite(reg, bpc); return;
277 delayRead(reg, bpc); return;
279 delayWrite(reg, bpc); return;
281 psxBSC[psxRegs.code >> 26]();
289 static u32 psxBranchNoDelay(void) {
293 code = (u32 *)PSXM(psxRegs.pc);
294 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
296 case 0x00: // SPECIAL
302 if (_Rd_) { _SetLink(_Rd_); }
310 return _BranchTarget_;
313 if (_i32(_rRs_) >= 0)
314 return _BranchTarget_;
317 if (_i32(_rRs_) < 0) {
319 return _BranchTarget_;
323 if (_i32(_rRs_) >= 0) {
325 return _BranchTarget_;
336 if (_i32(_rRs_) == _i32(_rRt_))
337 return _BranchTarget_;
340 if (_i32(_rRs_) != _i32(_rRt_))
341 return _BranchTarget_;
344 if (_i32(_rRs_) <= 0)
345 return _BranchTarget_;
349 return _BranchTarget_;
356 static int psxDelayBranchExec(u32 tar) {
361 psxRegs.cycle += BIAS;
366 static int psxDelayBranchTest(u32 tar1) {
367 u32 tar2, tmp1, tmp2;
369 tar2 = psxBranchNoDelay();
376 * Branch in delay slot:
377 * - execute 1 instruction at tar1
378 * - jump to tar2 (target of branch in delay slot; this branch
379 * has no normal delay slot, instruction at tar1 was fetched instead)
382 tmp1 = psxBranchNoDelay();
383 if (tmp1 == (u32)-1) {
384 return psxDelayBranchExec(tar2);
387 psxRegs.cycle += BIAS;
390 * Got a branch at tar1:
391 * - execute 1 instruction at tar2
392 * - jump to target of that branch (tmp1)
395 tmp2 = psxBranchNoDelay();
396 if (tmp2 == (u32)-1) {
397 return psxDelayBranchExec(tmp1);
400 psxRegs.cycle += BIAS;
403 * Got a branch at tar2:
404 * - execute 1 instruction at tmp1
405 * - jump to target of that branch (tmp2)
408 return psxDelayBranchExec(tmp2);
411 static void doBranch(u32 tar) {
415 branch2 = branch = 1;
418 // check for branch in delay slot
419 if (psxDelayBranchTest(tar))
422 code = (u32 *)PSXM(psxRegs.pc);
423 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
428 psxRegs.cycle += BIAS;
430 // check for load delay
431 tmp = psxRegs.code >> 26;
437 psxDelayTest(_Rt_, branchPC);
447 psxDelayTest(_Rt_, branchPC);
454 psxDelayTest(_Rt_, branchPC);
457 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
458 psxDelayTest(_Rt_, branchPC);
464 psxBSC[psxRegs.code >> 26]();
467 psxRegs.pc = branchPC;
472 /*********************************************************
473 * Arithmetic with immediate operand *
474 * Format: OP rt, rs, immediate *
475 *********************************************************/
476 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
477 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
478 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
479 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
480 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
481 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
482 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
484 /*********************************************************
485 * Register arithmetic *
486 * Format: OP rd, rs, rt *
487 *********************************************************/
488 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
489 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
490 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
491 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
492 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
493 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
494 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
495 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
496 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
497 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
499 /*********************************************************
500 * Register mult/div & Register trap logic *
501 * Format: OP rs, rt *
502 *********************************************************/
504 if (_i32(_rRt_) != 0) {
505 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
506 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
509 _i32(_rLo_) = _i32(_rRs_) >= 0 ? 0xffffffff : 1;
510 _i32(_rHi_) = _i32(_rRs_);
516 _rLo_ = _rRs_ / _rRt_;
517 _rHi_ = _rRs_ % _rRt_;
520 _i32(_rLo_) = 0xffffffff;
521 _i32(_rHi_) = _i32(_rRs_);
526 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
528 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
529 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
533 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
535 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
536 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
539 /*********************************************************
540 * Register branch logic *
541 * Format: OP rs, offset *
542 *********************************************************/
543 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
544 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
546 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
547 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
548 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
549 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
550 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
551 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
553 /*********************************************************
554 * Shift arithmetic with constant shift *
555 * Format: OP rd, rt, sa *
556 *********************************************************/
557 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
558 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
559 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
561 /*********************************************************
562 * Shift arithmetic with variant register shift *
563 * Format: OP rd, rt, rs *
564 *********************************************************/
565 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
566 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
567 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
569 /*********************************************************
570 * Load higher 16 bits of the first word in GPR with imm *
571 * Format: OP rt, immediate *
572 *********************************************************/
573 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
575 /*********************************************************
576 * Move from HI/LO to GPR *
578 *********************************************************/
579 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
580 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
582 /*********************************************************
583 * Move to GPR to HI/LO & Register jump *
585 *********************************************************/
586 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
587 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
589 /*********************************************************
590 * Special purpose instructions *
592 *********************************************************/
594 // Break exception - psx rom doens't handles this
599 psxException(0x20, branch);
603 // SysPrintf("psxRFE\n");
604 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
605 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
608 /*********************************************************
609 * Register branch logic *
610 * Format: OP rs, rt, offset *
611 *********************************************************/
612 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
614 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
615 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
617 /*********************************************************
619 * Format: OP target *
620 *********************************************************/
621 void psxJ() { doBranch(_JumpTarget_); }
622 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
624 /*********************************************************
626 * Format: OP rs, rd *
627 *********************************************************/
629 doBranch(_u32(_rRs_));
634 u32 temp = _u32(_rRs_);
635 if (_Rd_) { _SetLink(_Rd_); }
639 /*********************************************************
640 * Load and store for GPR *
641 * Format: OP rt, offset(base) *
642 *********************************************************/
644 #define _oB_ (_u32(_rRs_) + _Imm_)
648 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
656 _u32(_rRt_) = psxMemRead8(_oB_);
664 _i32(_rRt_) = (short)psxMemRead16(_oB_);
672 _u32(_rRt_) = psxMemRead16(_oB_);
680 _u32(_rRt_) = psxMemRead32(_oB_);
686 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
687 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
691 u32 shift = addr & 3;
692 u32 mem = psxMemRead32(addr & ~3);
695 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
696 ( mem << LWL_SHIFT[shift]);
699 Mem = 1234. Reg = abcd
701 0 4bcd (mem << 24) | (reg & 0x00ffffff)
702 1 34cd (mem << 16) | (reg & 0x0000ffff)
703 2 234d (mem << 8) | (reg & 0x000000ff)
704 3 1234 (mem ) | (reg & 0x00000000)
708 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
709 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
713 u32 shift = addr & 3;
714 u32 mem = psxMemRead32(addr & ~3);
717 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
718 ( mem >> LWR_SHIFT[shift]);
721 Mem = 1234. Reg = abcd
723 0 1234 (mem ) | (reg & 0x00000000)
724 1 a123 (mem >> 8) | (reg & 0xff000000)
725 2 ab12 (mem >> 16) | (reg & 0xffff0000)
726 3 abc1 (mem >> 24) | (reg & 0xffffff00)
730 void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
731 void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
732 void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
734 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
735 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
739 u32 shift = addr & 3;
740 u32 mem = psxMemRead32(addr & ~3);
742 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
743 ( mem & SWL_MASK[shift]) );
745 Mem = 1234. Reg = abcd
747 0 123a (reg >> 24) | (mem & 0xffffff00)
748 1 12ab (reg >> 16) | (mem & 0xffff0000)
749 2 1abc (reg >> 8) | (mem & 0xff000000)
750 3 abcd (reg ) | (mem & 0x00000000)
754 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
755 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
759 u32 shift = addr & 3;
760 u32 mem = psxMemRead32(addr & ~3);
762 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
763 ( mem & SWR_MASK[shift]) );
766 Mem = 1234. Reg = abcd
768 0 abcd (reg ) | (mem & 0x00000000)
769 1 bcd4 (reg << 8) | (mem & 0x000000ff)
770 2 cd34 (reg << 16) | (mem & 0x0000ffff)
771 3 d234 (reg << 24) | (mem & 0x00ffffff)
775 /*********************************************************
776 * Moves between GPR and COPx *
777 * Format: OP rt, fs *
778 *********************************************************/
779 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
780 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
782 void psxTestSWInts() {
783 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
784 psxRegs.CP0.n.Status & 0x1) {
785 psxRegs.CP0.n.Cause &= ~0x7c;
786 psxException(psxRegs.CP0.n.Cause, branch);
790 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 &= ~0x0300;
800 psxRegs.CP0.n.Cause |= val & 0x0300;
805 psxRegs.CP0.r[reg] = val;
810 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
811 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
813 /*********************************************************
814 * Unknow instruction (would generate an exception) *
816 *********************************************************/
819 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
836 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
839 void psxBASIC(struct psxCP2Regs *regs) {
844 // psxHLEt[psxRegs.code & 0xffff]();
845 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
848 void (*psxBSC[64])() = {
849 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
850 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
851 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
852 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
853 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
854 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
855 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
856 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
860 void (*psxSPC[64])() = {
861 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
862 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
863 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
864 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
865 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
866 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
867 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
868 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
871 void (*psxREG[32])() = {
872 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
873 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
874 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
875 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
878 void (*psxCP0[32])() = {
879 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
880 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
881 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
882 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
885 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
886 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
887 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
888 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
889 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
890 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
891 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
892 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
893 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
896 void (*psxCP2BSC[32])() = {
897 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
898 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
899 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
900 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
904 ///////////////////////////////////////////
906 static int intInit() {
910 static void intReset() {
919 void intExecuteBlock() {
921 while (!branch2) execI();
924 static void intClear(u32 Addr, u32 Size) {
927 static void intShutdown() {
930 // interpreter execution
932 u32 *code = (u32 *)PSXM(psxRegs.pc);
933 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
937 if (Config.Debug) ProcessDebug();
940 psxRegs.cycle += BIAS;
942 psxBSC[psxRegs.code >> 26]();