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));
43 void StartDebugger() {}
44 void ProcessDebug() {}
45 void StopDebugger() {}
55 void (*psxCP2[64])(struct psxCP2Regs *regs);
56 void (*psxCP2BSC[32])();
58 static void delayRead(int reg, u32 bpc) {
61 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
63 rold = psxRegs.GPR.r[reg];
64 psxBSC[psxRegs.code >> 26](); // branch delay load
65 rnew = psxRegs.GPR.r[reg];
71 psxRegs.GPR.r[reg] = rold;
72 execI(); // first branch opcode
73 psxRegs.GPR.r[reg] = rnew;
78 static void delayWrite(int reg, u32 bpc) {
80 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
82 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
83 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
85 // no changes from normal behavior
87 psxBSC[psxRegs.code >> 26]();
95 static void delayReadWrite(int reg, u32 bpc) {
97 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
99 // the branch delay load is skipped
107 // this defines shall be used with the tmp
108 // of the next func (instead of _Funct_...)
109 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
110 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
111 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
112 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
113 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
115 int psxTestLoadDelay(int reg, u32 tmp) {
116 if (tmp == 0) return 0; // NOP
118 case 0x00: // SPECIAL
121 case 0x02: case 0x03: // SRL/SRA
122 if (_tRd_ == reg && _tRt_ == reg) return 1; else
123 if (_tRt_ == reg) return 2; else
124 if (_tRd_ == reg) return 3;
128 if (_tRs_ == reg) return 2;
131 if (_tRd_ == reg && _tRs_ == reg) return 1; else
132 if (_tRs_ == reg) return 2; else
133 if (_tRd_ == reg) return 3;
136 // SYSCALL/BREAK just a break;
138 case 0x20: case 0x21: case 0x22: case 0x23:
139 case 0x24: case 0x25: case 0x26: case 0x27:
140 case 0x2a: case 0x2b: // ADD/ADDU...
141 case 0x04: case 0x06: case 0x07: // SLLV...
142 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
143 if (_tRt_ == reg || _tRs_ == reg) return 2; else
144 if (_tRd_ == reg) return 3;
147 case 0x10: case 0x12: // MFHI/MFLO
148 if (_tRd_ == reg) return 3;
150 case 0x11: case 0x13: // MTHI/MTLO
151 if (_tRs_ == reg) return 2;
154 case 0x18: case 0x19:
155 case 0x1a: case 0x1b: // MULT/DIV...
156 if (_tRt_ == reg || _tRs_ == reg) return 2;
163 case 0x00: case 0x01:
164 case 0x10: case 0x11: // BLTZ/BGEZ...
165 // Xenogears - lbu v0 / beq v0
166 // - no load delay (fixes battle loading)
169 if (_tRs_ == reg) return 2;
174 // J would be just a break;
176 if (31 == reg) return 3;
179 case 0x04: case 0x05: // BEQ/BNE
180 // Xenogears - lbu v0 / beq v0
181 // - no load delay (fixes battle loading)
184 if (_tRs_ == reg || _tRt_ == reg) return 2;
187 case 0x06: case 0x07: // BLEZ/BGTZ
188 // Xenogears - lbu v0 / beq v0
189 // - no load delay (fixes battle loading)
192 if (_tRs_ == reg) return 2;
195 case 0x08: case 0x09: case 0x0a: case 0x0b:
196 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
197 if (_tRt_ == reg && _tRs_ == reg) return 1; else
198 if (_tRs_ == reg) return 2; else
199 if (_tRt_ == reg) return 3;
203 if (_tRt_ == reg) return 3;
209 if (_tRt_ == reg) return 3;
212 if (_tRt_ == reg) return 3;
215 if (_tRt_ == reg) return 2;
218 if (_tRt_ == reg) return 2;
229 if (_tRt_ == reg) return 3;
232 if (_tRt_ == reg) return 3;
235 if (_tRt_ == reg) return 2;
238 if (_tRt_ == reg) return 2;
246 case 0x22: case 0x26: // LWL/LWR
247 if (_tRt_ == reg) return 3; else
248 if (_tRs_ == reg) return 2;
251 case 0x20: case 0x21: case 0x23:
252 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
253 if (_tRt_ == reg && _tRs_ == reg) return 1; else
254 if (_tRs_ == reg) return 2; else
255 if (_tRt_ == reg) return 3;
258 case 0x28: case 0x29: case 0x2a:
259 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
260 if (_tRt_ == reg || _tRs_ == reg) return 2;
263 case 0x32: case 0x3a: // LWC2/SWC2
264 if (_tRs_ == reg) return 2;
271 void psxDelayTest(int reg, u32 bpc) {
275 code = (u32 *)PSXM(bpc);
276 tmp = ((code == NULL) ? 0 : SWAP32(*code));
279 switch (psxTestLoadDelay(reg, tmp)) {
281 delayReadWrite(reg, bpc); return;
283 delayRead(reg, bpc); return;
285 delayWrite(reg, bpc); return;
287 psxBSC[psxRegs.code >> 26]();
295 static u32 psxBranchNoDelay(void) {
299 code = (u32 *)PSXM(psxRegs.pc);
300 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
302 case 0x00: // SPECIAL
308 if (_Rd_) { _SetLink(_Rd_); }
316 return _BranchTarget_;
319 if (_i32(_rRs_) >= 0)
320 return _BranchTarget_;
323 if (_i32(_rRs_) < 0) {
325 return _BranchTarget_;
329 if (_i32(_rRs_) >= 0) {
331 return _BranchTarget_;
342 if (_i32(_rRs_) == _i32(_rRt_))
343 return _BranchTarget_;
346 if (_i32(_rRs_) != _i32(_rRt_))
347 return _BranchTarget_;
350 if (_i32(_rRs_) <= 0)
351 return _BranchTarget_;
355 return _BranchTarget_;
362 static int psxDelayBranchExec(u32 tar) {
367 psxRegs.cycle += BIAS;
372 static int psxDelayBranchTest(u32 tar1) {
373 u32 tar2, tmp1, tmp2;
375 tar2 = psxBranchNoDelay();
382 * Branch in delay slot:
383 * - execute 1 instruction at tar1
384 * - jump to tar2 (target of branch in delay slot; this branch
385 * has no normal delay slot, instruction at tar1 was fetched instead)
388 tmp1 = psxBranchNoDelay();
389 if (tmp1 == (u32)-1) {
390 return psxDelayBranchExec(tar2);
393 psxRegs.cycle += BIAS;
396 * Got a branch at tar1:
397 * - execute 1 instruction at tar2
398 * - jump to target of that branch (tmp1)
401 tmp2 = psxBranchNoDelay();
402 if (tmp2 == (u32)-1) {
403 return psxDelayBranchExec(tmp1);
406 psxRegs.cycle += BIAS;
409 * Got a branch at tar2:
410 * - execute 1 instruction at tmp1
411 * - jump to target of that branch (tmp2)
414 return psxDelayBranchExec(tmp2);
417 static void doBranch(u32 tar) {
421 branch2 = branch = 1;
424 // check for branch in delay slot
425 if (psxDelayBranchTest(tar))
428 code = (u32 *)PSXM(psxRegs.pc);
429 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
434 psxRegs.cycle += BIAS;
436 // check for load delay
437 tmp = psxRegs.code >> 26;
443 psxDelayTest(_Rt_, branchPC);
453 psxDelayTest(_Rt_, branchPC);
460 psxDelayTest(_Rt_, branchPC);
463 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
464 psxDelayTest(_Rt_, branchPC);
470 psxBSC[psxRegs.code >> 26]();
473 psxRegs.pc = branchPC;
478 /*********************************************************
479 * Arithmetic with immediate operand *
480 * Format: OP rt, rs, immediate *
481 *********************************************************/
482 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
483 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
484 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
485 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
486 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
487 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
488 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
490 /*********************************************************
491 * Register arithmetic *
492 * Format: OP rd, rs, rt *
493 *********************************************************/
494 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
495 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
496 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
497 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
498 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
499 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
500 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
501 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
502 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
503 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
505 /*********************************************************
506 * Register mult/div & Register trap logic *
507 * Format: OP rs, rt *
508 *********************************************************/
511 _i32(_rHi_) = _i32(_rRs_);
512 if (_i32(_rRs_) & 0x80000000) {
515 _i32(_rLo_) = 0xFFFFFFFF;
517 } else if (_i32(_rRs_) == 0x80000000 && _i32(_rRt_) == 0xFFFFFFFF) {
518 _i32(_rLo_) = 0x80000000;
521 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
522 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
528 _rLo_ = _rRs_ / _rRt_;
529 _rHi_ = _rRs_ % _rRt_;
532 _i32(_rLo_) = 0xffffffff;
533 _i32(_rHi_) = _i32(_rRs_);
538 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
540 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
541 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
545 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
547 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
548 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
551 /*********************************************************
552 * Register branch logic *
553 * Format: OP rs, offset *
554 *********************************************************/
555 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
556 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
558 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
559 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
560 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
561 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
562 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
563 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
565 /*********************************************************
566 * Shift arithmetic with constant shift *
567 * Format: OP rd, rt, sa *
568 *********************************************************/
569 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
570 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
571 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
573 /*********************************************************
574 * Shift arithmetic with variant register shift *
575 * Format: OP rd, rt, rs *
576 *********************************************************/
577 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
578 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
579 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
581 /*********************************************************
582 * Load higher 16 bits of the first word in GPR with imm *
583 * Format: OP rt, immediate *
584 *********************************************************/
585 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
587 /*********************************************************
588 * Move from HI/LO to GPR *
590 *********************************************************/
591 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
592 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
594 /*********************************************************
595 * Move to GPR to HI/LO & Register jump *
597 *********************************************************/
598 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
599 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
601 /*********************************************************
602 * Special purpose instructions *
604 *********************************************************/
606 // Break exception - psx rom doens't handles this
611 psxException(0x20, branch);
615 // SysPrintf("psxRFE\n");
616 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
617 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
620 /*********************************************************
621 * Register branch logic *
622 * Format: OP rs, rt, offset *
623 *********************************************************/
624 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
626 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
627 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
629 /*********************************************************
631 * Format: OP target *
632 *********************************************************/
633 void psxJ() { doBranch(_JumpTarget_); }
634 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
636 /*********************************************************
638 * Format: OP rs, rd *
639 *********************************************************/
641 doBranch(_u32(_rRs_));
646 u32 temp = _u32(_rRs_);
647 if (_Rd_) { _SetLink(_Rd_); }
651 /*********************************************************
652 * Load and store for GPR *
653 * Format: OP rt, offset(base) *
654 *********************************************************/
656 #define _oB_ (_u32(_rRs_) + _Imm_)
660 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
668 _u32(_rRt_) = psxMemRead8(_oB_);
676 _i32(_rRt_) = (short)psxMemRead16(_oB_);
684 _u32(_rRt_) = psxMemRead16(_oB_);
692 _u32(_rRt_) = psxMemRead32(_oB_);
698 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
699 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
703 u32 shift = addr & 3;
704 u32 mem = psxMemRead32(addr & ~3);
707 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
708 ( mem << LWL_SHIFT[shift]);
711 Mem = 1234. Reg = abcd
713 0 4bcd (mem << 24) | (reg & 0x00ffffff)
714 1 34cd (mem << 16) | (reg & 0x0000ffff)
715 2 234d (mem << 8) | (reg & 0x000000ff)
716 3 1234 (mem ) | (reg & 0x00000000)
720 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
721 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
725 u32 shift = addr & 3;
726 u32 mem = psxMemRead32(addr & ~3);
729 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
730 ( mem >> LWR_SHIFT[shift]);
733 Mem = 1234. Reg = abcd
735 0 1234 (mem ) | (reg & 0x00000000)
736 1 a123 (mem >> 8) | (reg & 0xff000000)
737 2 ab12 (mem >> 16) | (reg & 0xffff0000)
738 3 abc1 (mem >> 24) | (reg & 0xffffff00)
742 void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
743 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
744 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
746 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
747 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
751 u32 shift = addr & 3;
752 u32 mem = psxMemRead32(addr & ~3);
754 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
755 ( mem & SWL_MASK[shift]) );
757 Mem = 1234. Reg = abcd
759 0 123a (reg >> 24) | (mem & 0xffffff00)
760 1 12ab (reg >> 16) | (mem & 0xffff0000)
761 2 1abc (reg >> 8) | (mem & 0xff000000)
762 3 abcd (reg ) | (mem & 0x00000000)
766 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
767 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
771 u32 shift = addr & 3;
772 u32 mem = psxMemRead32(addr & ~3);
774 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
775 ( mem & SWR_MASK[shift]) );
778 Mem = 1234. Reg = abcd
780 0 abcd (reg ) | (mem & 0x00000000)
781 1 bcd4 (reg << 8) | (mem & 0x000000ff)
782 2 cd34 (reg << 16) | (mem & 0x0000ffff)
783 3 d234 (reg << 24) | (mem & 0x00ffffff)
787 /*********************************************************
788 * Moves between GPR and COPx *
789 * Format: OP rt, fs *
790 *********************************************************/
791 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
792 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
794 void psxTestSWInts() {
795 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
796 psxRegs.CP0.n.Status & 0x1) {
797 psxRegs.CP0.n.Cause &= ~0x7c;
798 psxException(psxRegs.CP0.n.Cause, branch);
802 void MTC0(int reg, u32 val) {
803 // SysPrintf("MTC0 %d: %x\n", reg, val);
806 psxRegs.CP0.r[12] = val;
811 psxRegs.CP0.n.Cause &= ~0x0300;
812 psxRegs.CP0.n.Cause |= val & 0x0300;
817 psxRegs.CP0.r[reg] = val;
822 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
823 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
825 /*********************************************************
826 * Unknow instruction (would generate an exception) *
828 *********************************************************/
831 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
848 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
851 void psxBASIC(struct psxCP2Regs *regs) {
856 // psxHLEt[psxRegs.code & 0xffff]();
857 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
860 void (*psxBSC[64])() = {
861 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
862 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
863 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
864 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
865 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
866 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
867 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
868 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
872 void (*psxSPC[64])() = {
873 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
874 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
875 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
876 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
877 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
878 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
879 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
880 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
883 void (*psxREG[32])() = {
884 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
885 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
886 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
887 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
890 void (*psxCP0[32])() = {
891 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
892 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
893 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
894 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
897 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
898 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
899 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
900 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
901 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
902 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
903 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
904 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
905 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
908 void (*psxCP2BSC[32])() = {
909 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
910 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
911 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
912 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
916 ///////////////////////////////////////////
918 static int intInit() {
922 static void intReset() {
931 void intExecuteBlock() {
933 while (!branch2) execI();
936 static void intClear(u32 Addr, u32 Size) {
939 static void intShutdown() {
942 // interpreter execution
944 u32 *code = (u32 *)PSXM(psxRegs.pc);
945 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
949 if (Config.Debug) ProcessDebug();
952 psxRegs.cycle += BIAS;
954 psxBSC[psxRegs.code >> 26]();