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 *********************************************************/
510 if (_i32(_rRt_) != 0) {
511 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
512 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
515 _i32(_rLo_) = _i32(_rRs_) >= 0 ? 0xffffffff : 1;
516 _i32(_rHi_) = _i32(_rRs_);
522 _rLo_ = _rRs_ / _rRt_;
523 _rHi_ = _rRs_ % _rRt_;
526 _i32(_rLo_) = 0xffffffff;
527 _i32(_rHi_) = _i32(_rRs_);
532 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
534 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
535 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
539 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
541 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
542 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
545 /*********************************************************
546 * Register branch logic *
547 * Format: OP rs, offset *
548 *********************************************************/
549 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
550 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
552 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
553 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
554 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
555 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
556 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
557 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
559 /*********************************************************
560 * Shift arithmetic with constant shift *
561 * Format: OP rd, rt, sa *
562 *********************************************************/
563 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
564 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
565 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
567 /*********************************************************
568 * Shift arithmetic with variant register shift *
569 * Format: OP rd, rt, rs *
570 *********************************************************/
571 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
572 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
573 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
575 /*********************************************************
576 * Load higher 16 bits of the first word in GPR with imm *
577 * Format: OP rt, immediate *
578 *********************************************************/
579 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
581 /*********************************************************
582 * Move from HI/LO to GPR *
584 *********************************************************/
585 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
586 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
588 /*********************************************************
589 * Move to GPR to HI/LO & Register jump *
591 *********************************************************/
592 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
593 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
595 /*********************************************************
596 * Special purpose instructions *
598 *********************************************************/
600 // Break exception - psx rom doens't handles this
605 psxException(0x20, branch);
609 // SysPrintf("psxRFE\n");
610 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
611 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
614 /*********************************************************
615 * Register branch logic *
616 * Format: OP rs, rt, offset *
617 *********************************************************/
618 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
620 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
621 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
623 /*********************************************************
625 * Format: OP target *
626 *********************************************************/
627 void psxJ() { doBranch(_JumpTarget_); }
628 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
630 /*********************************************************
632 * Format: OP rs, rd *
633 *********************************************************/
635 doBranch(_u32(_rRs_));
640 u32 temp = _u32(_rRs_);
641 if (_Rd_) { _SetLink(_Rd_); }
645 /*********************************************************
646 * Load and store for GPR *
647 * Format: OP rt, offset(base) *
648 *********************************************************/
650 #define _oB_ (_u32(_rRs_) + _Imm_)
654 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
662 _u32(_rRt_) = psxMemRead8(_oB_);
670 _i32(_rRt_) = (short)psxMemRead16(_oB_);
678 _u32(_rRt_) = psxMemRead16(_oB_);
686 _u32(_rRt_) = psxMemRead32(_oB_);
692 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
693 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
697 u32 shift = addr & 3;
698 u32 mem = psxMemRead32(addr & ~3);
701 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
702 ( mem << LWL_SHIFT[shift]);
705 Mem = 1234. Reg = abcd
707 0 4bcd (mem << 24) | (reg & 0x00ffffff)
708 1 34cd (mem << 16) | (reg & 0x0000ffff)
709 2 234d (mem << 8) | (reg & 0x000000ff)
710 3 1234 (mem ) | (reg & 0x00000000)
714 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
715 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
719 u32 shift = addr & 3;
720 u32 mem = psxMemRead32(addr & ~3);
723 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
724 ( mem >> LWR_SHIFT[shift]);
727 Mem = 1234. Reg = abcd
729 0 1234 (mem ) | (reg & 0x00000000)
730 1 a123 (mem >> 8) | (reg & 0xff000000)
731 2 ab12 (mem >> 16) | (reg & 0xffff0000)
732 3 abc1 (mem >> 24) | (reg & 0xffffff00)
736 void psxSB() { psxMemWrite8 (_oB_, _rRt_ & 0xff); }
737 void psxSH() { psxMemWrite16(_oB_, _rRt_ & 0xffff); }
738 void psxSW() { psxMemWrite32(_oB_, _rRt_); }
740 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
741 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
745 u32 shift = addr & 3;
746 u32 mem = psxMemRead32(addr & ~3);
748 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
749 ( mem & SWL_MASK[shift]) );
751 Mem = 1234. Reg = abcd
753 0 123a (reg >> 24) | (mem & 0xffffff00)
754 1 12ab (reg >> 16) | (mem & 0xffff0000)
755 2 1abc (reg >> 8) | (mem & 0xff000000)
756 3 abcd (reg ) | (mem & 0x00000000)
760 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
761 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
765 u32 shift = addr & 3;
766 u32 mem = psxMemRead32(addr & ~3);
768 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
769 ( mem & SWR_MASK[shift]) );
772 Mem = 1234. Reg = abcd
774 0 abcd (reg ) | (mem & 0x00000000)
775 1 bcd4 (reg << 8) | (mem & 0x000000ff)
776 2 cd34 (reg << 16) | (mem & 0x0000ffff)
777 3 d234 (reg << 24) | (mem & 0x00ffffff)
781 /*********************************************************
782 * Moves between GPR and COPx *
783 * Format: OP rt, fs *
784 *********************************************************/
785 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
786 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
788 void psxTestSWInts() {
789 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
790 psxRegs.CP0.n.Status & 0x1) {
791 psxRegs.CP0.n.Cause &= ~0x7c;
792 psxException(psxRegs.CP0.n.Cause, branch);
796 void MTC0(int reg, u32 val) {
797 // SysPrintf("MTC0 %d: %x\n", reg, val);
800 psxRegs.CP0.r[12] = val;
805 psxRegs.CP0.n.Cause &= ~0x0300;
806 psxRegs.CP0.n.Cause |= val & 0x0300;
811 psxRegs.CP0.r[reg] = val;
816 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
817 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
819 /*********************************************************
820 * Unknow instruction (would generate an exception) *
822 *********************************************************/
825 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
842 psxCP2[_Funct_]((struct psxCP2Regs *)&psxRegs.CP2D);
845 void psxBASIC(struct psxCP2Regs *regs) {
850 // psxHLEt[psxRegs.code & 0xffff]();
851 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
854 void (*psxBSC[64])() = {
855 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
856 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
857 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
858 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
859 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
860 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
861 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
862 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
866 void (*psxSPC[64])() = {
867 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
868 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
869 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
870 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
871 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
872 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
873 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
874 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
877 void (*psxREG[32])() = {
878 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
879 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
880 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
881 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
884 void (*psxCP0[32])() = {
885 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
886 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
887 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
888 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
891 void (*psxCP2[64])(struct psxCP2Regs *regs) = {
892 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
893 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
894 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
895 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
896 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
897 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
898 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
899 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
902 void (*psxCP2BSC[32])() = {
903 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
904 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
905 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
906 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
910 ///////////////////////////////////////////
912 static int intInit() {
916 static void intReset() {
925 void intExecuteBlock() {
927 while (!branch2) execI();
930 static void intClear(u32 Addr, u32 Size) {
933 static void intShutdown() {
936 // interpreter execution
938 u32 *code = (u32 *)PSXM(psxRegs.pc);
939 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
943 if (Config.Debug) ProcessDebug();
946 psxRegs.cycle += BIAS;
948 psxBSC[psxRegs.code >> 26]();