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"
29 static int branch = 0;
30 static int branch2 = 0;
33 // These macros are used to assemble the repassembler functions
36 #define debugI() PSXCPU_LOG("%s\n", disR3000AF(psxRegs.code, psxRegs.pc));
49 void (*psxCP2BSC[32])();
51 static void delayRead(int reg, u32 bpc) {
54 // SysPrintf("delayRead at %x!\n", psxRegs.pc);
56 rold = psxRegs.GPR.r[reg];
57 psxBSC[psxRegs.code >> 26](); // branch delay load
58 rnew = psxRegs.GPR.r[reg];
64 psxRegs.GPR.r[reg] = rold;
65 execI(); // first branch opcode
66 psxRegs.GPR.r[reg] = rnew;
71 static void delayWrite(int reg, u32 bpc) {
73 /* SysPrintf("delayWrite at %x!\n", psxRegs.pc);
75 SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4));
76 SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/
78 // no changes from normal behavior
80 psxBSC[psxRegs.code >> 26]();
88 static void delayReadWrite(int reg, u32 bpc) {
90 // SysPrintf("delayReadWrite at %x!\n", psxRegs.pc);
92 // the branch delay load is skipped
100 // this defines shall be used with the tmp
101 // of the next func (instead of _Funct_...)
102 #define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register
103 #define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register
104 #define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register
105 #define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register
106 #define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register
108 int psxTestLoadDelay(int reg, u32 tmp) {
109 if (tmp == 0) return 0; // NOP
111 case 0x00: // SPECIAL
114 case 0x02: case 0x03: // SRL/SRA
115 if (_tRd_ == reg && _tRt_ == reg) return 1; else
116 if (_tRt_ == reg) return 2; else
117 if (_tRd_ == reg) return 3;
121 if (_tRs_ == reg) return 2;
124 if (_tRd_ == reg && _tRs_ == reg) return 1; else
125 if (_tRs_ == reg) return 2; else
126 if (_tRd_ == reg) return 3;
129 // SYSCALL/BREAK just a break;
131 case 0x20: case 0x21: case 0x22: case 0x23:
132 case 0x24: case 0x25: case 0x26: case 0x27:
133 case 0x2a: case 0x2b: // ADD/ADDU...
134 case 0x04: case 0x06: case 0x07: // SLLV...
135 if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) return 1; else
136 if (_tRt_ == reg || _tRs_ == reg) return 2; else
137 if (_tRd_ == reg) return 3;
140 case 0x10: case 0x12: // MFHI/MFLO
141 if (_tRd_ == reg) return 3;
143 case 0x11: case 0x13: // MTHI/MTLO
144 if (_tRs_ == reg) return 2;
147 case 0x18: case 0x19:
148 case 0x1a: case 0x1b: // MULT/DIV...
149 if (_tRt_ == reg || _tRs_ == reg) return 2;
156 case 0x00: case 0x02:
157 case 0x10: case 0x12: // BLTZ/BGEZ...
158 if (_tRs_ == reg) return 2;
163 // J would be just a break;
165 if (31 == reg) return 3;
168 case 0x04: case 0x05: // BEQ/BNE
169 if (_tRs_ == reg || _tRt_ == reg) return 2;
172 case 0x06: case 0x07: // BLEZ/BGTZ
173 if (_tRs_ == reg) return 2;
176 case 0x08: case 0x09: case 0x0a: case 0x0b:
177 case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU...
178 if (_tRt_ == reg && _tRs_ == reg) return 1; else
179 if (_tRs_ == reg) return 2; else
180 if (_tRt_ == reg) return 3;
184 if (_tRt_ == reg) return 3;
190 if (_tRt_ == reg) return 3;
193 if (_tRt_ == reg) return 3;
196 if (_tRt_ == reg) return 2;
199 if (_tRt_ == reg) return 2;
210 if (_tRt_ == reg) return 3;
213 if (_tRt_ == reg) return 3;
216 if (_tRt_ == reg) return 2;
219 if (_tRt_ == reg) return 2;
227 case 0x22: case 0x26: // LWL/LWR
228 if (_tRt_ == reg) return 3; else
229 if (_tRs_ == reg) return 2;
232 case 0x20: case 0x21: case 0x23:
233 case 0x24: case 0x25: // LB/LH/LW/LBU/LHU
234 if (_tRt_ == reg && _tRs_ == reg) return 1; else
235 if (_tRs_ == reg) return 2; else
236 if (_tRt_ == reg) return 3;
239 case 0x28: case 0x29: case 0x2a:
240 case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR
241 if (_tRt_ == reg || _tRs_ == reg) return 2;
244 case 0x32: case 0x3a: // LWC2/SWC2
245 if (_tRs_ == reg) return 2;
252 void psxDelayTest(int reg, u32 bpc) {
256 code = (u32 *)PSXM(bpc);
257 tmp = ((code == NULL) ? 0 : SWAP32(*code));
260 switch (psxTestLoadDelay(reg, tmp)) {
262 delayReadWrite(reg, bpc); return;
264 delayRead(reg, bpc); return;
266 delayWrite(reg, bpc); return;
268 psxBSC[psxRegs.code >> 26]();
276 static u32 psxBranchNoDelay(void) {
280 code = (u32 *)PSXM(psxRegs.pc);
281 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
283 case 0x00: // SPECIAL
289 if (_Rd_) { _SetLink(_Rd_); }
297 return _BranchTarget_;
300 if (_i32(_rRs_) >= 0)
301 return _BranchTarget_;
304 if (_i32(_rRs_) < 0) {
306 return _BranchTarget_;
310 if (_i32(_rRs_) >= 0) {
312 return _BranchTarget_;
323 if (_i32(_rRs_) == _i32(_rRt_))
324 return _BranchTarget_;
327 if (_i32(_rRs_) != _i32(_rRt_))
328 return _BranchTarget_;
331 if (_i32(_rRs_) <= 0)
332 return _BranchTarget_;
336 return _BranchTarget_;
343 static int psxDelayBranchExec(u32 tar) {
348 psxRegs.cycle += BIAS;
353 static int psxDelayBranchTest(u32 tar1) {
354 u32 tar2, tmp1, tmp2;
356 tar2 = psxBranchNoDelay();
363 * Branch in delay slot:
364 * - execute 1 instruction at tar1
365 * - jump to tar2 (target of branch in delay slot; this branch
366 * has no normal delay slot, instruction at tar1 was fetched instead)
369 tmp1 = psxBranchNoDelay();
370 if (tmp1 == (u32)-1) {
371 return psxDelayBranchExec(tar2);
374 psxRegs.cycle += BIAS;
377 * Got a branch at tar1:
378 * - execute 1 instruction at tar2
379 * - jump to target of that branch (tmp1)
382 tmp2 = psxBranchNoDelay();
383 if (tmp2 == (u32)-1) {
384 return psxDelayBranchExec(tmp1);
387 psxRegs.cycle += BIAS;
390 * Got a branch at tar2:
391 * - execute 1 instruction at tmp1
392 * - jump to target of that branch (tmp2)
395 return psxDelayBranchExec(tmp2);
398 __inline void doBranch(u32 tar) {
402 branch2 = branch = 1;
405 // check for branch in delay slot
406 if (psxDelayBranchTest(tar))
409 code = (u32 *)PSXM(psxRegs.pc);
410 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
415 psxRegs.cycle += BIAS;
417 // check for load delay
418 tmp = psxRegs.code >> 26;
424 psxDelayTest(_Rt_, branchPC);
434 psxDelayTest(_Rt_, branchPC);
441 psxDelayTest(_Rt_, branchPC);
444 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
445 psxDelayTest(_Rt_, branchPC);
451 psxBSC[psxRegs.code >> 26]();
454 psxRegs.pc = branchPC;
459 /*********************************************************
460 * Arithmetic with immediate operand *
461 * Format: OP rt, rs, immediate *
462 *********************************************************/
463 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
464 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
465 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
466 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
467 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
468 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
469 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
471 /*********************************************************
472 * Register arithmetic *
473 * Format: OP rd, rs, rt *
474 *********************************************************/
475 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
476 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
477 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
478 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
479 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
480 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
481 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
482 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
483 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
484 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
486 /*********************************************************
487 * Register mult/div & Register trap logic *
488 * Format: OP rs, rt *
489 *********************************************************/
491 if (_i32(_rRt_) != 0) {
492 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
493 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
499 _rLo_ = _rRs_ / _rRt_;
500 _rHi_ = _rRs_ % _rRt_;
505 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
507 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
508 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
512 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
514 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
515 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
518 /*********************************************************
519 * Register branch logic *
520 * Format: OP rs, offset *
521 *********************************************************/
522 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
523 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
525 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
526 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
527 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
528 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
529 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
530 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
532 /*********************************************************
533 * Shift arithmetic with constant shift *
534 * Format: OP rd, rt, sa *
535 *********************************************************/
536 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
537 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
538 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
540 /*********************************************************
541 * Shift arithmetic with variant register shift *
542 * Format: OP rd, rt, rs *
543 *********************************************************/
544 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
545 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
546 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
548 /*********************************************************
549 * Load higher 16 bits of the first word in GPR with imm *
550 * Format: OP rt, immediate *
551 *********************************************************/
552 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
554 /*********************************************************
555 * Move from HI/LO to GPR *
557 *********************************************************/
558 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
559 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
561 /*********************************************************
562 * Move to GPR to HI/LO & Register jump *
564 *********************************************************/
565 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
566 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
568 /*********************************************************
569 * Special purpose instructions *
571 *********************************************************/
573 // Break exception - psx rom doens't handles this
578 psxException(0x20, branch);
582 // SysPrintf("psxRFE\n");
583 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
584 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
587 /*********************************************************
588 * Register branch logic *
589 * Format: OP rs, rt, offset *
590 *********************************************************/
591 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
593 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
594 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
596 /*********************************************************
598 * Format: OP target *
599 *********************************************************/
600 void psxJ() { doBranch(_JumpTarget_); }
601 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
603 /*********************************************************
605 * Format: OP rs, rd *
606 *********************************************************/
608 doBranch(_u32(_rRs_));
613 u32 temp = _u32(_rRs_);
614 if (_Rd_) { _SetLink(_Rd_); }
618 /*********************************************************
619 * Load and store for GPR *
620 * Format: OP rt, offset(base) *
621 *********************************************************/
623 #define _oB_ (_u32(_rRs_) + _Imm_)
627 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
635 _u32(_rRt_) = psxMemRead8(_oB_);
643 _i32(_rRt_) = (short)psxMemRead16(_oB_);
651 _u32(_rRt_) = psxMemRead16(_oB_);
659 _u32(_rRt_) = psxMemRead32(_oB_);
665 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
666 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
670 u32 shift = addr & 3;
671 u32 mem = psxMemRead32(addr & ~3);
674 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
675 ( mem << LWL_SHIFT[shift]);
678 Mem = 1234. Reg = abcd
680 0 4bcd (mem << 24) | (reg & 0x00ffffff)
681 1 34cd (mem << 16) | (reg & 0x0000ffff)
682 2 234d (mem << 8) | (reg & 0x000000ff)
683 3 1234 (mem ) | (reg & 0x00000000)
687 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
688 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
692 u32 shift = addr & 3;
693 u32 mem = psxMemRead32(addr & ~3);
696 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
697 ( mem >> LWR_SHIFT[shift]);
700 Mem = 1234. Reg = abcd
702 0 1234 (mem ) | (reg & 0x00000000)
703 1 a123 (mem >> 8) | (reg & 0xff000000)
704 2 ab12 (mem >> 16) | (reg & 0xffff0000)
705 3 abc1 (mem >> 24) | (reg & 0xffffff00)
709 void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
710 void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
711 void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
713 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
714 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
718 u32 shift = addr & 3;
719 u32 mem = psxMemRead32(addr & ~3);
721 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
722 ( mem & SWL_MASK[shift]) );
724 Mem = 1234. Reg = abcd
726 0 123a (reg >> 24) | (mem & 0xffffff00)
727 1 12ab (reg >> 16) | (mem & 0xffff0000)
728 2 1abc (reg >> 8) | (mem & 0xff000000)
729 3 abcd (reg ) | (mem & 0x00000000)
733 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
734 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
738 u32 shift = addr & 3;
739 u32 mem = psxMemRead32(addr & ~3);
741 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
742 ( mem & SWR_MASK[shift]) );
745 Mem = 1234. Reg = abcd
747 0 abcd (reg ) | (mem & 0x00000000)
748 1 bcd4 (reg << 8) | (mem & 0x000000ff)
749 2 cd34 (reg << 16) | (mem & 0x0000ffff)
750 3 d234 (reg << 24) | (mem & 0x00ffffff)
754 /*********************************************************
755 * Moves between GPR and COPx *
756 * Format: OP rt, fs *
757 *********************************************************/
758 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
759 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
761 void psxTestSWInts() {
762 // the next code is untested, if u know please
763 // tell me if it works ok or not (linuzappz)
764 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
765 psxRegs.CP0.n.Status & 0x1) {
766 psxException(psxRegs.CP0.n.Cause, branch);
770 __inline void MTC0(int reg, u32 val) {
771 // SysPrintf("MTC0 %d: %x\n", reg, val);
774 psxRegs.CP0.r[12] = val;
779 psxRegs.CP0.n.Cause = val & ~(0xfc00);
784 psxRegs.CP0.r[reg] = val;
789 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
790 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
792 /*********************************************************
793 * Unknow instruction (would generate an exception) *
795 *********************************************************/
798 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
823 // psxHLEt[psxRegs.code & 0xffff]();
824 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
827 void (*psxBSC[64])() = {
828 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
829 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
830 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
831 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
832 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
833 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
834 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
835 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
839 void (*psxSPC[64])() = {
840 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
841 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
842 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
843 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
844 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
845 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
846 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
847 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
850 void (*psxREG[32])() = {
851 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
852 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
853 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
854 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
857 void (*psxCP0[32])() = {
858 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
859 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
860 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
861 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
864 void (*psxCP2[64])() = {
865 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
866 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
867 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
868 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
869 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
870 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
871 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
872 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
875 void (*psxCP2BSC[32])() = {
876 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
877 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
878 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
879 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
883 ///////////////////////////////////////////
885 static int intInit() {
889 static void intReset() {
898 void intExecuteBlock() {
900 while (!branch2) execI();
903 static void intClear(u32 Addr, u32 Size) {
906 static void intShutdown() {
909 // interpreter execution
910 inline void execI() {
911 u32 *code = (u32 *)PSXM(psxRegs.pc);
912 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
916 if (Config.Debug) ProcessDebug();
919 psxRegs.cycle += BIAS;
921 psxBSC[psxRegs.code >> 26]();