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 *********************************************************/
505 _i32(_rHi_) = _i32(_rRs_);
506 if (_i32(_rRs_) & 0x80000000) {
509 _i32(_rLo_) = 0xFFFFFFFF;
512 * Notaz said that this was "not needed" for ARM platforms and could slow it down so let's disable for ARM.
513 * This fixes a crash issue that can happen when running Amidog's CPU test.
514 * (It still stays stuck to a black screen but at least it doesn't crash anymore)
516 #if !defined(__arm__) && !defined(__aarch64__)
517 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
518 _i32(_rLo_) = 0x80000000;
522 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
523 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
529 _rLo_ = _rRs_ / _rRt_;
530 _rHi_ = _rRs_ % _rRt_;
533 _i32(_rLo_) = 0xffffffff;
534 _i32(_rHi_) = _i32(_rRs_);
539 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
541 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
542 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
546 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
548 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
549 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
552 /*********************************************************
553 * Register branch logic *
554 * Format: OP rs, offset *
555 *********************************************************/
556 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
557 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
559 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
560 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
561 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
562 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
563 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
564 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
566 /*********************************************************
567 * Shift arithmetic with constant shift *
568 * Format: OP rd, rt, sa *
569 *********************************************************/
570 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
571 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
572 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
574 /*********************************************************
575 * Shift arithmetic with variant register shift *
576 * Format: OP rd, rt, rs *
577 *********************************************************/
578 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
579 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
580 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
582 /*********************************************************
583 * Load higher 16 bits of the first word in GPR with imm *
584 * Format: OP rt, immediate *
585 *********************************************************/
586 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
588 /*********************************************************
589 * Move from HI/LO to GPR *
591 *********************************************************/
592 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
593 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
595 /*********************************************************
596 * Move to GPR to HI/LO & Register jump *
598 *********************************************************/
599 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
600 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
602 /*********************************************************
603 * Special purpose instructions *
605 *********************************************************/
607 // Break exception - psx rom doens't handles this
612 psxException(0x20, branch);
616 // SysPrintf("psxRFE\n");
617 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
618 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
621 /*********************************************************
622 * Register branch logic *
623 * Format: OP rs, rt, offset *
624 *********************************************************/
625 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
627 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
628 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
630 /*********************************************************
632 * Format: OP target *
633 *********************************************************/
634 void psxJ() { doBranch(_JumpTarget_); }
635 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
637 /*********************************************************
639 * Format: OP rs, rd *
640 *********************************************************/
642 doBranch(_u32(_rRs_));
647 u32 temp = _u32(_rRs_);
648 if (_Rd_) { _SetLink(_Rd_); }
652 /*********************************************************
653 * Load and store for GPR *
654 * Format: OP rt, offset(base) *
655 *********************************************************/
657 #define _oB_ (_u32(_rRs_) + _Imm_)
661 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
669 _u32(_rRt_) = psxMemRead8(_oB_);
677 _i32(_rRt_) = (short)psxMemRead16(_oB_);
685 _u32(_rRt_) = psxMemRead16(_oB_);
693 _u32(_rRt_) = psxMemRead32(_oB_);
699 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
700 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
704 u32 shift = addr & 3;
705 u32 mem = psxMemRead32(addr & ~3);
708 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
709 ( mem << LWL_SHIFT[shift]);
712 Mem = 1234. Reg = abcd
714 0 4bcd (mem << 24) | (reg & 0x00ffffff)
715 1 34cd (mem << 16) | (reg & 0x0000ffff)
716 2 234d (mem << 8) | (reg & 0x000000ff)
717 3 1234 (mem ) | (reg & 0x00000000)
721 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
722 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
726 u32 shift = addr & 3;
727 u32 mem = psxMemRead32(addr & ~3);
730 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
731 ( mem >> LWR_SHIFT[shift]);
734 Mem = 1234. Reg = abcd
736 0 1234 (mem ) | (reg & 0x00000000)
737 1 a123 (mem >> 8) | (reg & 0xff000000)
738 2 ab12 (mem >> 16) | (reg & 0xffff0000)
739 3 abc1 (mem >> 24) | (reg & 0xffffff00)
743 void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
744 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
745 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
747 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
748 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
752 u32 shift = addr & 3;
753 u32 mem = psxMemRead32(addr & ~3);
755 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
756 ( mem & SWL_MASK[shift]) );
758 Mem = 1234. Reg = abcd
760 0 123a (reg >> 24) | (mem & 0xffffff00)
761 1 12ab (reg >> 16) | (mem & 0xffff0000)
762 2 1abc (reg >> 8) | (mem & 0xff000000)
763 3 abcd (reg ) | (mem & 0x00000000)
767 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
768 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
772 u32 shift = addr & 3;
773 u32 mem = psxMemRead32(addr & ~3);
775 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
776 ( mem & SWR_MASK[shift]) );
779 Mem = 1234. Reg = abcd
781 0 abcd (reg ) | (mem & 0x00000000)
782 1 bcd4 (reg << 8) | (mem & 0x000000ff)
783 2 cd34 (reg << 16) | (mem & 0x0000ffff)
784 3 d234 (reg << 24) | (mem & 0x00ffffff)
788 /*********************************************************
789 * Moves between GPR and COPx *
790 * Format: OP rt, fs *
791 *********************************************************/
792 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
793 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
795 void psxTestSWInts() {
796 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
797 psxRegs.CP0.n.Status & 0x1) {
798 psxRegs.CP0.n.Cause &= ~0x7c;
799 psxException(psxRegs.CP0.n.Cause, branch);
803 void MTC0(int reg, u32 val) {
804 // SysPrintf("MTC0 %d: %x\n", reg, val);
807 psxRegs.CP0.r[12] = val;
812 psxRegs.CP0.n.Cause &= ~0x0300;
813 psxRegs.CP0.n.Cause |= val & 0x0300;
818 psxRegs.CP0.r[reg] = val;
823 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
824 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
826 /*********************************************************
827 * Unknow instruction (would generate an exception) *
829 *********************************************************/
832 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
849 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
852 void psxBASIC(struct psxCP2Regs *regs) {
857 // psxHLEt[psxRegs.code & 0xffff]();
858 // psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
859 uint32_t hleCode = psxRegs.code & 0x03ffffff;
860 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
867 void (*psxBSC[64])() = {
868 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
869 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
870 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
871 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
872 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
873 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
874 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
875 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
879 void (*psxSPC[64])() = {
880 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
881 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
882 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
883 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
884 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
885 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
886 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
887 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
890 void (*psxREG[32])() = {
891 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
892 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
893 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
894 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
897 void (*psxCP0[32])() = {
898 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
899 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
900 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
901 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
904 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
905 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
906 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
907 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
908 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
909 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
910 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
911 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
912 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
915 void (*psxCP2BSC[32])() = {
916 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
917 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
918 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
919 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
923 ///////////////////////////////////////////
925 static int intInit() {
929 static void intReset() {
938 void intExecuteBlock() {
940 while (!branch2) execI();
943 static void intClear(u32 Addr, u32 Size) {
946 static void intShutdown() {
949 // interpreter execution
951 u32 *code = (u32 *)PSXM(psxRegs.pc);
952 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
956 if (Config.Debug) ProcessDebug();
959 psxRegs.cycle += BIAS;
961 psxBSC[psxRegs.code >> 26]();