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));
45 void StartDebugger() {}
46 void ProcessDebug() {}
47 void StopDebugger() {}
57 void (*psxCP2[64])(struct psxCP2Regs *regs);
58 void (*psxCP2BSC[32])();
60 static void delayRead(int reg, u32 bpc) {
63 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
65 rold = psxRegs.GPR.r[reg];
66 psxBSC[psxRegs.code >> 26](); // branch delay load
67 rnew = psxRegs.GPR.r[reg];
73 psxRegs.GPR.r[reg] = rold;
74 execI(); // first branch opcode
75 psxRegs.GPR.r[reg] = rnew;
80 static void delayWrite(int reg, u32 bpc) {
82 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
84 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
85 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
87 // no changes from normal behavior
89 psxBSC[psxRegs.code >> 26]();
97 static void delayReadWrite(int reg, u32 bpc) {
99 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
101 // the branch delay load is skipped
109 // this defines shall be used with the tmp
110 // of the next func (instead of _Funct_...)
111 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
112 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
113 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
114 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
115 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
117 int psxTestLoadDelay(int reg, u32 tmp) {
118 if (tmp == 0) return 0; // NOP
120 case 0x00: // SPECIAL
123 case 0x02: case 0x03: // SRL/SRA
124 if (_tRd_ == reg && _tRt_ == reg) return 1; else
125 if (_tRt_ == reg) return 2; else
126 if (_tRd_ == reg) return 3;
130 if (_tRs_ == reg) return 2;
133 if (_tRd_ == reg && _tRs_ == reg) return 1; else
134 if (_tRs_ == reg) return 2; else
135 if (_tRd_ == reg) return 3;
138 // SYSCALL/BREAK just a break;
140 case 0x20: case 0x21: case 0x22: case 0x23:
141 case 0x24: case 0x25: case 0x26: case 0x27:
142 case 0x2a: case 0x2b: // ADD/ADDU...
143 case 0x04: case 0x06: case 0x07: // SLLV...
144 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
145 if (_tRt_ == reg || _tRs_ == reg) return 2; else
146 if (_tRd_ == reg) return 3;
149 case 0x10: case 0x12: // MFHI/MFLO
150 if (_tRd_ == reg) return 3;
152 case 0x11: case 0x13: // MTHI/MTLO
153 if (_tRs_ == reg) return 2;
156 case 0x18: case 0x19:
157 case 0x1a: case 0x1b: // MULT/DIV...
158 if (_tRt_ == reg || _tRs_ == reg) return 2;
165 case 0x00: case 0x01:
166 case 0x10: case 0x11: // BLTZ/BGEZ...
167 // Xenogears - lbu v0 / beq v0
168 // - no load delay (fixes battle loading)
171 if (_tRs_ == reg) return 2;
176 // J would be just a break;
178 if (31 == reg) return 3;
181 case 0x04: case 0x05: // BEQ/BNE
182 // Xenogears - lbu v0 / beq v0
183 // - no load delay (fixes battle loading)
186 if (_tRs_ == reg || _tRt_ == reg) return 2;
189 case 0x06: case 0x07: // BLEZ/BGTZ
190 // Xenogears - lbu v0 / beq v0
191 // - no load delay (fixes battle loading)
194 if (_tRs_ == reg) return 2;
197 case 0x08: case 0x09: case 0x0a: case 0x0b:
198 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
199 if (_tRt_ == reg && _tRs_ == reg) return 1; else
200 if (_tRs_ == reg) return 2; else
201 if (_tRt_ == reg) return 3;
205 if (_tRt_ == reg) return 3;
211 if (_tRt_ == reg) return 3;
214 if (_tRt_ == reg) return 3;
217 if (_tRt_ == reg) return 2;
220 if (_tRt_ == reg) return 2;
231 if (_tRt_ == reg) return 3;
234 if (_tRt_ == reg) return 3;
237 if (_tRt_ == reg) return 2;
240 if (_tRt_ == reg) return 2;
248 case 0x22: case 0x26: // LWL/LWR
249 if (_tRt_ == reg) return 3; else
250 if (_tRs_ == reg) return 2;
253 case 0x20: case 0x21: case 0x23:
254 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
255 if (_tRt_ == reg && _tRs_ == reg) return 1; else
256 if (_tRs_ == reg) return 2; else
257 if (_tRt_ == reg) return 3;
260 case 0x28: case 0x29: case 0x2a:
261 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
262 if (_tRt_ == reg || _tRs_ == reg) return 2;
265 case 0x32: case 0x3a: // LWC2/SWC2
266 if (_tRs_ == reg) return 2;
273 void psxDelayTest(int reg, u32 bpc) {
277 code = (u32 *)PSXM(bpc);
278 tmp = ((code == NULL) ? 0 : SWAP32(*code));
281 switch (psxTestLoadDelay(reg, tmp)) {
283 delayReadWrite(reg, bpc); return;
285 delayRead(reg, bpc); return;
287 delayWrite(reg, bpc); return;
289 psxBSC[psxRegs.code >> 26]();
297 static u32 psxBranchNoDelay(void) {
301 code = (u32 *)PSXM(psxRegs.pc);
302 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
304 case 0x00: // SPECIAL
310 if (_Rd_) { _SetLink(_Rd_); }
318 return _BranchTarget_;
321 if (_i32(_rRs_) >= 0)
322 return _BranchTarget_;
325 if (_i32(_rRs_) < 0) {
327 return _BranchTarget_;
331 if (_i32(_rRs_) >= 0) {
333 return _BranchTarget_;
344 if (_i32(_rRs_) == _i32(_rRt_))
345 return _BranchTarget_;
348 if (_i32(_rRs_) != _i32(_rRt_))
349 return _BranchTarget_;
352 if (_i32(_rRs_) <= 0)
353 return _BranchTarget_;
357 return _BranchTarget_;
364 static int psxDelayBranchExec(u32 tar) {
369 psxRegs.cycle += BIAS;
374 static int psxDelayBranchTest(u32 tar1) {
375 u32 tar2, tmp1, tmp2;
377 tar2 = psxBranchNoDelay();
384 * Branch in delay slot:
385 * - execute 1 instruction at tar1
386 * - jump to tar2 (target of branch in delay slot; this branch
387 * has no normal delay slot, instruction at tar1 was fetched instead)
390 tmp1 = psxBranchNoDelay();
391 if (tmp1 == (u32)-1) {
392 return psxDelayBranchExec(tar2);
395 psxRegs.cycle += BIAS;
398 * Got a branch at tar1:
399 * - execute 1 instruction at tar2
400 * - jump to target of that branch (tmp1)
403 tmp2 = psxBranchNoDelay();
404 if (tmp2 == (u32)-1) {
405 return psxDelayBranchExec(tmp1);
408 psxRegs.cycle += BIAS;
411 * Got a branch at tar2:
412 * - execute 1 instruction at tmp1
413 * - jump to target of that branch (tmp2)
416 return psxDelayBranchExec(tmp2);
419 static void doBranch(u32 tar) {
423 branch2 = branch = 1;
426 // check for branch in delay slot
427 if (psxDelayBranchTest(tar))
430 code = (u32 *)PSXM(psxRegs.pc);
431 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
436 psxRegs.cycle += BIAS;
438 // check for load delay
439 tmp = psxRegs.code >> 26;
445 psxDelayTest(_Rt_, branchPC);
455 psxDelayTest(_Rt_, branchPC);
462 psxDelayTest(_Rt_, branchPC);
465 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
466 psxDelayTest(_Rt_, branchPC);
472 psxBSC[psxRegs.code >> 26]();
475 psxRegs.pc = branchPC;
480 /*********************************************************
481 * Arithmetic with immediate operand *
482 * Format: OP rt, rs, immediate *
483 *********************************************************/
484 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
485 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
486 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
487 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
488 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
489 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
490 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
492 /*********************************************************
493 * Register arithmetic *
494 * Format: OP rd, rs, rt *
495 *********************************************************/
496 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
497 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
498 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
499 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
500 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
501 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
502 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
503 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
504 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
505 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
507 /*********************************************************
508 * Register mult/div & Register trap logic *
509 * Format: OP rs, rt *
510 *********************************************************/
513 _i32(_rHi_) = _i32(_rRs_);
514 if (_i32(_rRs_) & 0x80000000) {
517 _i32(_rLo_) = 0xFFFFFFFF;
519 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
520 _i32(_rLo_) = 0x80000000;
523 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
524 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
530 _rLo_ = _rRs_ / _rRt_;
531 _rHi_ = _rRs_ % _rRt_;
534 _i32(_rLo_) = 0xffffffff;
535 _i32(_rHi_) = _i32(_rRs_);
540 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
542 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
543 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
547 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
549 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
550 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
553 /*********************************************************
554 * Register branch logic *
555 * Format: OP rs, offset *
556 *********************************************************/
557 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
558 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
560 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
561 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
562 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
563 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
564 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
565 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
567 /*********************************************************
568 * Shift arithmetic with constant shift *
569 * Format: OP rd, rt, sa *
570 *********************************************************/
571 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
572 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
573 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
575 /*********************************************************
576 * Shift arithmetic with variant register shift *
577 * Format: OP rd, rt, rs *
578 *********************************************************/
579 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
580 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
581 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
583 /*********************************************************
584 * Load higher 16 bits of the first word in GPR with imm *
585 * Format: OP rt, immediate *
586 *********************************************************/
587 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
589 /*********************************************************
590 * Move from HI/LO to GPR *
592 *********************************************************/
593 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
594 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
596 /*********************************************************
597 * Move to GPR to HI/LO & Register jump *
599 *********************************************************/
600 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
601 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
603 /*********************************************************
604 * Special purpose instructions *
606 *********************************************************/
608 // Break exception - psx rom doens't handles this
613 psxException(0x20, branch);
617 // SysPrintf("psxRFE\n");
618 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
619 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
622 /*********************************************************
623 * Register branch logic *
624 * Format: OP rs, rt, offset *
625 *********************************************************/
626 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
628 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
629 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
631 /*********************************************************
633 * Format: OP target *
634 *********************************************************/
635 void psxJ() { doBranch(_JumpTarget_); }
636 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
638 /*********************************************************
640 * Format: OP rs, rd *
641 *********************************************************/
643 doBranch(_u32(_rRs_));
648 u32 temp = _u32(_rRs_);
649 if (_Rd_) { _SetLink(_Rd_); }
653 /*********************************************************
654 * Load and store for GPR *
655 * Format: OP rt, offset(base) *
656 *********************************************************/
658 #define _oB_ (_u32(_rRs_) + _Imm_)
662 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
670 _u32(_rRt_) = psxMemRead8(_oB_);
678 _i32(_rRt_) = (short)psxMemRead16(_oB_);
686 _u32(_rRt_) = psxMemRead16(_oB_);
694 _u32(_rRt_) = psxMemRead32(_oB_);
700 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
701 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
705 u32 shift = addr & 3;
706 u32 mem = psxMemRead32(addr & ~3);
709 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
710 ( mem << LWL_SHIFT[shift]);
713 Mem = 1234. Reg = abcd
715 0 4bcd (mem << 24) | (reg & 0x00ffffff)
716 1 34cd (mem << 16) | (reg & 0x0000ffff)
717 2 234d (mem << 8) | (reg & 0x000000ff)
718 3 1234 (mem ) | (reg & 0x00000000)
722 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
723 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
727 u32 shift = addr & 3;
728 u32 mem = psxMemRead32(addr & ~3);
731 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
732 ( mem >> LWR_SHIFT[shift]);
735 Mem = 1234. Reg = abcd
737 0 1234 (mem ) | (reg & 0x00000000)
738 1 a123 (mem >> 8) | (reg & 0xff000000)
739 2 ab12 (mem >> 16) | (reg & 0xffff0000)
740 3 abc1 (mem >> 24) | (reg & 0xffffff00)
744 void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
745 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
746 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
748 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
749 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
753 u32 shift = addr & 3;
754 u32 mem = psxMemRead32(addr & ~3);
756 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
757 ( mem & SWL_MASK[shift]) );
759 Mem = 1234. Reg = abcd
761 0 123a (reg >> 24) | (mem & 0xffffff00)
762 1 12ab (reg >> 16) | (mem & 0xffff0000)
763 2 1abc (reg >> 8) | (mem & 0xff000000)
764 3 abcd (reg ) | (mem & 0x00000000)
768 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
769 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
773 u32 shift = addr & 3;
774 u32 mem = psxMemRead32(addr & ~3);
776 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
777 ( mem & SWR_MASK[shift]) );
780 Mem = 1234. Reg = abcd
782 0 abcd (reg ) | (mem & 0x00000000)
783 1 bcd4 (reg << 8) | (mem & 0x000000ff)
784 2 cd34 (reg << 16) | (mem & 0x0000ffff)
785 3 d234 (reg << 24) | (mem & 0x00ffffff)
789 /*********************************************************
790 * Moves between GPR and COPx *
791 * Format: OP rt, fs *
792 *********************************************************/
793 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
794 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
796 void psxTestSWInts() {
797 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
798 psxRegs.CP0.n.Status & 0x1) {
799 psxRegs.CP0.n.Cause &= ~0x7c;
800 psxException(psxRegs.CP0.n.Cause, branch);
804 void MTC0(int reg, u32 val) {
805 // SysPrintf("MTC0 %d: %x\n", reg, val);
808 psxRegs.CP0.r[12] = val;
813 psxRegs.CP0.n.Cause &= ~0x0300;
814 psxRegs.CP0.n.Cause |= val & 0x0300;
819 psxRegs.CP0.r[reg] = val;
824 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
825 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
827 /*********************************************************
828 * Unknow instruction (would generate an exception) *
830 *********************************************************/
833 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
850 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
853 void psxBASIC(struct psxCP2Regs *regs) {
858 // psxHLEt[psxRegs.code & 0xffff]();
859 // psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
860 uint32_t hleCode = psxRegs.code & 0x03ffffff;
861 if (hleCode >= (sizeof(psxHLEt) / sizeof(psxHLEt[0]))) {
868 void (*psxBSC[64])() = {
869 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
870 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
871 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
872 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
873 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
874 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
875 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
876 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
880 void (*psxSPC[64])() = {
881 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
882 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
883 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
884 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
885 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
886 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
887 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
888 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
891 void (*psxREG[32])() = {
892 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
893 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
894 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
895 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
898 void (*psxCP0[32])() = {
899 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
900 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
901 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
902 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
905 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
906 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
907 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
908 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
909 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
910 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
911 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
912 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
913 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
916 void (*psxCP2BSC[32])() = {
917 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
918 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
919 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
920 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
924 ///////////////////////////////////////////
926 static int intInit() {
930 static void intReset() {
939 void intExecuteBlock() {
941 while (!branch2) execI();
944 static void intClear(u32 Addr, u32 Size) {
947 static void intShutdown() {
950 // interpreter execution
952 u32 *code = (u32 *)PSXM(psxRegs.pc);
953 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
957 if (Config.Debug) ProcessDebug();
960 psxRegs.cycle += BIAS;
962 psxBSC[psxRegs.code >> 26]();