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 __inline void doBranch(u32 tar) {
280 branch2 = branch = 1;
283 code = (u32 *)PSXM(psxRegs.pc);
284 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
289 psxRegs.cycle += BIAS;
291 // check for load delay
292 tmp = psxRegs.code >> 26;
298 psxDelayTest(_Rt_, branchPC);
308 psxDelayTest(_Rt_, branchPC);
315 psxDelayTest(_Rt_, branchPC);
318 if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR
319 psxDelayTest(_Rt_, branchPC);
325 psxBSC[psxRegs.code >> 26]();
328 psxRegs.pc = branchPC;
333 /*********************************************************
334 * Arithmetic with immediate operand *
335 * Format: OP rt, rs, immediate *
336 *********************************************************/
337 void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
338 void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im
339 void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
340 void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
341 void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
342 void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
343 void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_Imm_); } // Rt = Rs < Im (Unsigned)
345 /*********************************************************
346 * Register arithmetic *
347 * Format: OP rd, rs, rt *
348 *********************************************************/
349 void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
350 void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
351 void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
352 void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
353 void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
354 void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
355 void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
356 void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
357 void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
358 void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
360 /*********************************************************
361 * Register mult/div & Register trap logic *
362 * Format: OP rs, rt *
363 *********************************************************/
365 if (_i32(_rRt_) != 0) {
366 _i32(_rLo_) = _i32(_rRs_) / _i32(_rRt_);
367 _i32(_rHi_) = _i32(_rRs_) % _i32(_rRt_);
373 _rLo_ = _rRs_ / _rRt_;
374 _rHi_ = _rRs_ % _rRt_;
379 u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_));
381 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
382 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
386 u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_));
388 psxRegs.GPR.n.lo = (u32)(res & 0xffffffff);
389 psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff);
392 /*********************************************************
393 * Register branch logic *
394 * Format: OP rs, offset *
395 *********************************************************/
396 #define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_);
397 #define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); }
399 void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0
400 void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link
401 void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0
402 void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0
403 void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0
404 void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link
406 /*********************************************************
407 * Shift arithmetic with constant shift *
408 * Format: OP rd, rt, sa *
409 *********************************************************/
410 void psxSLL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
411 void psxSRA() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
412 void psxSRL() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
414 /*********************************************************
415 * Shift arithmetic with variant register shift *
416 * Format: OP rd, rt, rs *
417 *********************************************************/
418 void psxSLLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
419 void psxSRAV() { if (!_Rd_) return; _i32(_rRd_) = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
420 void psxSRLV() { if (!_Rd_) return; _u32(_rRd_) = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical)
422 /*********************************************************
423 * Load higher 16 bits of the first word in GPR with imm *
424 * Format: OP rt, immediate *
425 *********************************************************/
426 void psxLUI() { if (!_Rt_) return; _u32(_rRt_) = psxRegs.code << 16; } // Upper halfword of Rt = Im
428 /*********************************************************
429 * Move from HI/LO to GPR *
431 *********************************************************/
432 void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
433 void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
435 /*********************************************************
436 * Move to GPR to HI/LO & Register jump *
438 *********************************************************/
439 void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
440 void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
442 /*********************************************************
443 * Special purpose instructions *
445 *********************************************************/
447 // Break exception - psx rom doens't handles this
452 psxException(0x20, branch);
456 // SysPrintf("psxRFE\n");
457 psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
458 ((psxRegs.CP0.n.Status & 0x3c) >> 2);
461 /*********************************************************
462 * Register branch logic *
463 * Format: OP rs, rt, offset *
464 *********************************************************/
465 #define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) doBranch(_BranchTarget_);
467 void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt
468 void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt
470 /*********************************************************
472 * Format: OP target *
473 *********************************************************/
474 void psxJ() { doBranch(_JumpTarget_); }
475 void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); }
477 /*********************************************************
479 * Format: OP rs, rd *
480 *********************************************************/
482 doBranch(_u32(_rRs_));
487 u32 temp = _u32(_rRs_);
488 if (_Rd_) { _SetLink(_Rd_); }
492 /*********************************************************
493 * Load and store for GPR *
494 * Format: OP rt, offset(base) *
495 *********************************************************/
497 #define _oB_ (_u32(_rRs_) + _Imm_)
501 _i32(_rRt_) = (signed char)psxMemRead8(_oB_);
509 _u32(_rRt_) = psxMemRead8(_oB_);
517 _i32(_rRt_) = (short)psxMemRead16(_oB_);
525 _u32(_rRt_) = psxMemRead16(_oB_);
533 _u32(_rRt_) = psxMemRead32(_oB_);
539 u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 };
540 u32 LWL_SHIFT[4] = { 24, 16, 8, 0 };
544 u32 shift = addr & 3;
545 u32 mem = psxMemRead32(addr & ~3);
548 _u32(_rRt_) = ( _u32(_rRt_) & LWL_MASK[shift]) |
549 ( mem << LWL_SHIFT[shift]);
552 Mem = 1234. Reg = abcd
554 0 4bcd (mem << 24) | (reg & 0x00ffffff)
555 1 34cd (mem << 16) | (reg & 0x0000ffff)
556 2 234d (mem << 8) | (reg & 0x000000ff)
557 3 1234 (mem ) | (reg & 0x00000000)
561 u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 };
562 u32 LWR_SHIFT[4] = { 0, 8, 16, 24 };
566 u32 shift = addr & 3;
567 u32 mem = psxMemRead32(addr & ~3);
570 _u32(_rRt_) = ( _u32(_rRt_) & LWR_MASK[shift]) |
571 ( mem >> LWR_SHIFT[shift]);
574 Mem = 1234. Reg = abcd
576 0 1234 (mem ) | (reg & 0x00000000)
577 1 a123 (mem >> 8) | (reg & 0xff000000)
578 2 ab12 (mem >> 16) | (reg & 0xffff0000)
579 3 abc1 (mem >> 24) | (reg & 0xffffff00)
583 void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); }
584 void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); }
585 void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); }
587 u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 };
588 u32 SWL_SHIFT[4] = { 24, 16, 8, 0 };
592 u32 shift = addr & 3;
593 u32 mem = psxMemRead32(addr & ~3);
595 psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) |
596 ( mem & SWL_MASK[shift]) );
598 Mem = 1234. Reg = abcd
600 0 123a (reg >> 24) | (mem & 0xffffff00)
601 1 12ab (reg >> 16) | (mem & 0xffff0000)
602 2 1abc (reg >> 8) | (mem & 0xff000000)
603 3 abcd (reg ) | (mem & 0x00000000)
607 u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff };
608 u32 SWR_SHIFT[4] = { 0, 8, 16, 24 };
612 u32 shift = addr & 3;
613 u32 mem = psxMemRead32(addr & ~3);
615 psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) |
616 ( mem & SWR_MASK[shift]) );
619 Mem = 1234. Reg = abcd
621 0 abcd (reg ) | (mem & 0x00000000)
622 1 bcd4 (reg << 8) | (mem & 0x000000ff)
623 2 cd34 (reg << 16) | (mem & 0x0000ffff)
624 3 d234 (reg << 24) | (mem & 0x00ffffff)
628 /*********************************************************
629 * Moves between GPR and COPx *
630 * Format: OP rt, fs *
631 *********************************************************/
632 void psxMFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
633 void psxCFC0() { if (!_Rt_) return; _i32(_rRt_) = (int)_rFs_; }
635 void psxTestSWInts() {
636 // the next code is untested, if u know please
637 // tell me if it works ok or not (linuzappz)
638 if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 &&
639 psxRegs.CP0.n.Status & 0x1) {
640 psxException(psxRegs.CP0.n.Cause, branch);
644 __inline void MTC0(int reg, u32 val) {
645 // SysPrintf("MTC0 %d: %x\n", reg, val);
648 psxRegs.CP0.r[12] = val;
653 psxRegs.CP0.n.Cause = val & ~(0xfc00);
658 psxRegs.CP0.r[reg] = val;
663 void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); }
664 void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); }
666 /*********************************************************
667 * Unknow instruction (would generate an exception) *
669 *********************************************************/
672 PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code);
697 // psxHLEt[psxRegs.code & 0xffff]();
698 psxHLEt[psxRegs.code & 0x07](); // HDHOSHY experimental patch
701 void (*psxBSC[64])() = {
702 psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
703 psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
704 psxCOP0 , psxNULL , psxCOP2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
705 psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
706 psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL,
707 psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL,
708 psxNULL , psxNULL , gteLWC2, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL,
709 psxNULL , psxNULL , gteSWC2, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL
713 void (*psxSPC[64])() = {
714 psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV,
715 psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL,
716 psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL,
717 psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL,
718 psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR ,
719 psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL,
720 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL,
721 psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL
724 void (*psxREG[32])() = {
725 psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
726 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
727 psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
728 psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
731 void (*psxCP0[32])() = {
732 psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL,
733 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
734 psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
735 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
738 void (*psxCP2[64])() = {
739 psxBASIC, gteRTPS , psxNULL , psxNULL, psxNULL, psxNULL , gteNCLIP, psxNULL, // 00
740 psxNULL , psxNULL , psxNULL , psxNULL, gteOP , psxNULL , psxNULL , psxNULL, // 08
741 gteDPCS , gteINTPL, gteMVMVA, gteNCDS, gteCDP , psxNULL , gteNCDT , psxNULL, // 10
742 psxNULL , psxNULL , psxNULL , gteNCCS, gteCC , psxNULL , gteNCS , psxNULL, // 18
743 gteNCT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
744 gteSQR , gteDCPL , gteDPCT , psxNULL, psxNULL, gteAVSZ3, gteAVSZ4, psxNULL, // 28
745 gteRTPT , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
746 psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, gteGPF , gteGPL , gteNCCT // 38
749 void (*psxCP2BSC[32])() = {
750 gteMFC2, psxNULL, gteCFC2, psxNULL, gteMTC2, psxNULL, gteCTC2, psxNULL,
751 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
752 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
753 psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
757 ///////////////////////////////////////////
759 static int intInit() {
763 static void intReset() {
766 static void intExecute() {
771 static void intExecuteBlock() {
773 while (!branch2) execI();
776 static void intClear(u32 Addr, u32 Size) {
779 static void intShutdown() {
782 // interpreter execution
783 inline void execI() {
784 u32 *code = (u32 *)PSXM(psxRegs.pc);
785 psxRegs.code = ((code == NULL) ? 0 : SWAP32(*code));
789 if (Config.Debug) ProcessDebug();
792 psxRegs.cycle += BIAS;
794 psxBSC[psxRegs.code >> 26]();