Mercurial > audlegacy-plugins
diff src/sexypsf/PsxInterpreter.c @ 12:3da1b8942b8b trunk
[svn] - remove src/Input src/Output src/Effect src/General src/Visualization src/Container
author | nenolod |
---|---|
date | Mon, 18 Sep 2006 03:14:20 -0700 |
parents | src/Input/sexypsf/PsxInterpreter.c@13389e613d67 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/sexypsf/PsxInterpreter.c Mon Sep 18 03:14:20 2006 -0700 @@ -0,0 +1,747 @@ +/* Pcsx - Pc Psx Emulator + * Copyright (C) 1999-2002 Pcsx Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <stdlib.h> + +#include "PsxCommon.h" + +static int branch; +static int branch2; +static u32 branchPC; + +// These macros are used to assemble the repassembler functions + +// if(!PSXM(psxRegs.pc)) puts("Whoops"); +// Fix this... + +// printf("%08x ", psxRegs.pc); + +#define execI() { \ + psxRegs.code = BFLIP32(PSXMu32(psxRegs.pc)); \ + \ + psxRegs.pc+= 4; psxRegs.cycle++; \ + psxBSC[psxRegs.code >> 26](); \ +} + +// Subsets +static void (*psxBSC[64])(); +static void (*psxSPC[64])(); +static void (*psxREG[32])(); +static void (*psxCP0[32])(); + +static void delayRead(int reg, u32 bpc) { + u32 rold, rnew; + +// SysPrintf("delayRead at %x!\n", psxRegs.pc); + + rold = psxRegs.GPR.r[reg]; + psxBSC[psxRegs.code >> 26](); // branch delay load + rnew = psxRegs.GPR.r[reg]; + + psxRegs.pc = bpc; + + psxBranchTest(); + + psxRegs.GPR.r[reg] = rold; + execI(); // first branch opcode + psxRegs.GPR.r[reg] = rnew; + + branch = 0; +} + +static void delayWrite(int reg, u32 bpc) { + +/* SysPrintf("delayWrite at %x!\n", psxRegs.pc); + +// SysPrintf("%s\n", disR3000AF(psxRegs.code, psxRegs.pc-4)); +// SysPrintf("%s\n", disR3000AF(PSXMu32(bpc), bpc));*/ + + // no changes from normal behavior + + psxBSC[psxRegs.code >> 26](); + + branch = 0; + psxRegs.pc = bpc; + + psxBranchTest(); +} + +static void delayReadWrite(int reg, u32 bpc) { + +// SysPrintf("delayReadWrite at %x!\n", psxRegs.pc); + + // the branch delay load is skipped + + branch = 0; + psxRegs.pc = bpc; + + psxBranchTest(); +} + +// this defines shall be used with the tmp +// of the next func (instead of _Funct_...) +#define _tFunct_ ((tmp ) & 0x3F) // The funct part of the instruction register +#define _tRd_ ((tmp >> 11) & 0x1F) // The rd part of the instruction register +#define _tRt_ ((tmp >> 16) & 0x1F) // The rt part of the instruction register +#define _tRs_ ((tmp >> 21) & 0x1F) // The rs part of the instruction register +#define _tSa_ ((tmp >> 6) & 0x1F) // The sa part of the instruction register + +static void psxDelayTest(u32 reg, u32 bpc) { + u32 tmp; + + tmp = BFLIP32(PSXMu32(bpc)); + branch = 1; + + switch (tmp >> 26) { + case 0x00: // SPECIAL + switch (_tFunct_) { + case 0x00: // SLL + if (!tmp) break; // NOP + case 0x02: case 0x03: // SRL/SRA + if (_tRd_ == reg && _tRt_ == reg) { + delayReadWrite(reg, bpc); return; + } else if (_tRt_ == reg) { + delayRead(reg, bpc); return; + } else if (_tRd_ == reg) { + delayWrite(reg, bpc); return; + } + break; + + case 0x08: // JR + if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + case 0x09: // JALR + if (_tRd_ == reg && _tRs_ == reg) { + delayReadWrite(reg, bpc); return; + } else if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } else if (_tRd_ == reg) { + delayWrite(reg, bpc); return; + } + break; + + // SYSCALL/BREAK just a break; + + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x2a: case 0x2b: // ADD/ADDU... + case 0x04: case 0x06: case 0x07: // SLLV... + if (_tRd_ == reg && (_tRt_ == reg || _tRs_ == reg)) { + delayReadWrite(reg, bpc); return; + } else if (_tRt_ == reg || _tRs_ == reg) { + delayRead(reg, bpc); return; + } else if (_tRd_ == reg) { + delayWrite(reg, bpc); return; + } + break; + + case 0x10: case 0x12: // MFHI/MFLO + if (_tRd_ == reg) { + delayWrite(reg, bpc); return; + } + break; + case 0x11: case 0x13: // MTHI/MTLO + if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + + case 0x18: case 0x19: + case 0x1a: case 0x1b: // MULT/DIV... + if (_tRt_ == reg || _tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + } + break; + + case 0x01: // REGIMM + switch (_tRt_) { + case 0x00: case 0x02: + case 0x10: case 0x12: // BLTZ/BGEZ... + if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + } + break; + + // J would be just a break; + case 0x03: // JAL + if (31 == reg) { + delayWrite(reg, bpc); return; + } + break; + + case 0x04: case 0x05: // BEQ/BNE + if (_tRs_ == reg || _tRt_ == reg) { + delayRead(reg, bpc); return; + } + break; + + case 0x06: case 0x07: // BLEZ/BGTZ + if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + + case 0x08: case 0x09: case 0x0a: case 0x0b: + case 0x0c: case 0x0d: case 0x0e: // ADDI/ADDIU... + if (_tRt_ == reg && _tRs_ == reg) { + delayReadWrite(reg, bpc); return; + } else if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } else if (_tRt_ == reg) { + delayWrite(reg, bpc); return; + } + break; + + case 0x0f: // LUI + if (_tRt_ == reg) { + delayWrite(reg, bpc); return; + } + break; + + case 0x10: // COP0 + switch (_tFunct_) { + case 0x00: // MFC0 + if (_tRt_ == reg) { delayWrite(reg, bpc); return; } + break; + case 0x02: // CFC0 + if (_tRt_ == reg) { delayWrite(reg, bpc); return; } + break; + case 0x04: // MTC0 + if (_tRt_ == reg) { delayRead(reg, bpc); return; } + break; + case 0x06: // CTC0 + if (_tRt_ == reg) { delayRead(reg, bpc); return; } + break; + // RFE just a break; + } + break; + + case 0x22: case 0x26: // LWL/LWR + if (_tRt_ == reg) { + delayReadWrite(reg, bpc); return; + } else if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + + case 0x20: case 0x21: case 0x23: + case 0x24: case 0x25: // LB/LH/LW/LBU/LHU + if (_tRt_ == reg && _tRs_ == reg) { + delayReadWrite(reg, bpc); return; + } else if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } else if (_tRt_ == reg) { + delayWrite(reg, bpc); return; + } + break; + + case 0x28: case 0x29: case 0x2a: + case 0x2b: case 0x2e: // SB/SH/SWL/SW/SWR + if (_tRt_ == reg || _tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + + case 0x32: case 0x3a: // LWC2/SWC2 + if (_tRs_ == reg) { + delayRead(reg, bpc); return; + } + break; + } + psxBSC[psxRegs.code >> 26](); + + branch = 0; + psxRegs.pc = bpc; + + psxBranchTest(); +} + +static void psxNULL(void); + +static INLINE void doBranch(u32 tar) { + u32 tmp; + + branch2 = branch = 1; + branchPC = tar; + + psxRegs.code = BFLIP32(PSXMu32(psxRegs.pc)); + + psxRegs.pc+= 4; psxRegs.cycle++; + + // check for load delay + tmp = psxRegs.code >> 26; + switch (tmp) { + case 0x10: // COP0 + switch (_Rs_) { + case 0x00: // MFC0 + case 0x02: // CFC0 + psxDelayTest(_Rt_, branchPC); + return; + } + break; + case 0x32: // LWC2 + psxDelayTest(_Rt_, branchPC); + return; + default: + if (tmp >= 0x20 && tmp <= 0x26) { // LB/LH/LWL/LW/LBU/LHU/LWR + psxDelayTest(_Rt_, branchPC); + return; + } + break; + } + + psxBSC[psxRegs.code >> 26](); + + if((psxRegs.pc-8)==branchPC && !(psxRegs.code>>26)) + { + //printf("%08x\n",psxRegs.code>>26); + CounterDeadLoopSkip(); + } + branch = 0; + psxRegs.pc = branchPC; + + psxBranchTest(); +} + +/********************************************************* +* Arithmetic with immediate operand * +* Format: OP rt, rs, immediate * +*********************************************************/ +static void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow) +static void psxADDIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im +static void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im +static void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im +static void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im +static void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed) +static void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < ((u32)_ImmU_); } // Rt = Rs < Im (Unsigned) + +/********************************************************* +* Register arithmetic * +* Format: OP rd, rs, rt * +*********************************************************/ +static void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow) +static void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt +static void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow) +static void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt +static void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt +static void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt +static void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt +static void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt +static void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed) +static void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned) + +/********************************************************* +* Register mult/div & Register trap logic * +* Format: OP rs, rt * +*********************************************************/ +static void psxDIV() { + if (_i32(_rRt_) != 0) { + _rLo_ = _i32(_rRs_) / _i32(_rRt_); + _rHi_ = _i32(_rRs_) % _i32(_rRt_); + } +} + +static void psxDIVU() { + if (_rRt_ != 0) { + _rLo_ = _rRs_ / _rRt_; + _rHi_ = _rRs_ % _rRt_; + } +} + +static void psxMULT() { + u64 res = (s64)((s64)_i32(_rRs_) * (s64)_i32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +static void psxMULTU() { + u64 res = (u64)((u64)_u32(_rRs_) * (u64)_u32(_rRt_)); + + psxRegs.GPR.n.lo = (u32)(res & 0xffffffff); + psxRegs.GPR.n.hi = (u32)((res >> 32) & 0xffffffff); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, offset * +*********************************************************/ +#define RepZBranchi32(op) if(_i32(_rRs_) op 0) doBranch(_BranchTarget_); +#define RepZBranchLinki32(op) if(_i32(_rRs_) op 0) { _SetLink(31); doBranch(_BranchTarget_); } + +static void psxBGEZ() { RepZBranchi32(>=) } // Branch if Rs >= 0 +static void psxBGEZAL() { RepZBranchLinki32(>=) } // Branch if Rs >= 0 and link +static void psxBGTZ() { RepZBranchi32(>) } // Branch if Rs > 0 +static void psxBLEZ() { RepZBranchi32(<=) } // Branch if Rs <= 0 +static void psxBLTZ() { RepZBranchi32(<) } // Branch if Rs < 0 +static void psxBLTZAL() { RepZBranchLinki32(<) } // Branch if Rs < 0 and link + +/********************************************************* +* Shift arithmetic with constant shift * +* Format: OP rd, rt, sa * +*********************************************************/ +static void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa +static void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic) +static void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical) + +/********************************************************* +* Shift arithmetic with variant register shift * +* Format: OP rd, rt, rs * +*********************************************************/ +static void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs +static void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic) +static void psxSRLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (logical) + +/********************************************************* +* Load higher 16 bits of the first word in GPR with imm * +* Format: OP rt, immediate * +*********************************************************/ +static void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im + +/********************************************************* +* Move from HI/LO to GPR * +* Format: OP rd * +*********************************************************/ +static void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi +static void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo + +/********************************************************* +* Move to GPR to HI/LO & Register jump * +* Format: OP rs * +*********************************************************/ +static void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs +static void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs + +/********************************************************* +* Special purpose instructions * +* Format: OP * +*********************************************************/ +static void psxBREAK() { + // Break exception - psx rom doens't handles this +} + +static void psxSYSCALL() { + psxRegs.pc -= 4; + psxException(0x20, branch); +} + +static void psxRFE() { + psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) | + ((psxRegs.CP0.n.Status & 0x3c) >> 2); +} + +/********************************************************* +* Register branch logic * +* Format: OP rs, rt, offset * +*********************************************************/ +#define RepBranchi32(op) if(_i32(_rRs_) op _i32(_rRt_)) { doBranch(_BranchTarget_); } + +static void psxBEQ() { RepBranchi32(==) } // Branch if Rs == Rt +static void psxBNE() { RepBranchi32(!=) } // Branch if Rs != Rt + +/********************************************************* +* Jump to target * +* Format: OP target * +*********************************************************/ +static void psxJ() { doBranch(_JumpTarget_); } +static void psxJAL() { _SetLink(31); doBranch(_JumpTarget_); } + +/********************************************************* +* Register jump * +* Format: OP rs, rd * +*********************************************************/ +static void psxJR() { doBranch(_u32(_rRs_)); } +static void psxJALR() { if (_Rd_) { _SetLink(_Rd_); } doBranch(_u32(_rRs_)); } + +/********************************************************* +* Load and store for GPR * +* Format: OP rt, offset(base) * +*********************************************************/ + +#define _oB_ (_u32(_rRs_) + _Imm_) + +static void psxLB() { + if (_Rt_) { + _rRt_ = (s8)psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +static void psxLBU() { + if (_Rt_) { + _rRt_ = psxMemRead8(_oB_); + } else { + psxMemRead8(_oB_); + } +} + +static void psxLH() { + if (_Rt_) { + _rRt_ = (s16)psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +static void psxLHU() { + if (_Rt_) { + _rRt_ = psxMemRead16(_oB_); + } else { + psxMemRead16(_oB_); + } +} + +static void psxLW() { + if (_Rt_) { + _rRt_ = psxMemRead32(_oB_); + } else { + psxMemRead32(_oB_); + } +} + +static u32 LWL_MASK[4] = { 0xffffff, 0xffff, 0xff, 0 }; +static u32 LWL_SHIFT[4] = { 24, 16, 8, 0 }; + +static void psxLWL() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & LWL_MASK[shift]) | + ( mem << LWL_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 4bcd (mem << 24) | (reg & 0x00ffffff) + 1 34cd (mem << 16) | (reg & 0x0000ffff) + 2 234d (mem << 8) | (reg & 0x000000ff) + 3 1234 (mem ) | (reg & 0x00000000) + */ +} + +static u32 LWR_MASK[4] = { 0, 0xff000000, 0xffff0000, 0xffffff00 }; +static u32 LWR_SHIFT[4] = { 0, 8, 16, 24 }; + +static void psxLWR() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + if (!_Rt_) return; + _rRt_ = ( _u32(_rRt_) & LWR_MASK[shift]) | + ( mem >> LWR_SHIFT[shift]); + + /* + Mem = 1234. Reg = abcd + + 0 1234 (mem ) | (reg & 0x00000000) + 1 a123 (mem >> 8) | (reg & 0xff000000) + 2 ab12 (mem >> 16) | (reg & 0xffff0000) + 3 abc1 (mem >> 24) | (reg & 0xffffff00) + */ +} + +static void psxSB() { psxMemWrite8 (_oB_, _u8 (_rRt_)); } +static void psxSH() { psxMemWrite16(_oB_, _u16(_rRt_)); } +static void psxSW() { psxMemWrite32(_oB_, _u32(_rRt_)); } + +static const u32 SWL_MASK[4] = { 0xffffff00, 0xffff0000, 0xff000000, 0 }; +static const u32 SWL_SHIFT[4] = { 24, 16, 8, 0 }; + +static void psxSWL() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + psxMemWrite32(addr & ~3, (_u32(_rRt_) >> SWL_SHIFT[shift]) | + ( mem & SWL_MASK[shift]) ); + /* + Mem = 1234. Reg = abcd + + 0 123a (reg >> 24) | (mem & 0xffffff00) + 1 12ab (reg >> 16) | (mem & 0xffff0000) + 2 1abc (reg >> 8) | (mem & 0xff000000) + 3 abcd (reg ) | (mem & 0x00000000) + */ +} + +static const u32 SWR_MASK[4] = { 0, 0xff, 0xffff, 0xffffff }; +static const u32 SWR_SHIFT[4] = { 0, 8, 16, 24 }; + +static void psxSWR() { + u32 addr = _oB_; + u32 shift = addr & 3; + u32 mem = psxMemRead32(addr & ~3); + + psxMemWrite32(addr & ~3, (_u32(_rRt_) << SWR_SHIFT[shift]) | + ( mem & SWR_MASK[shift]) ); + + /* + Mem = 1234. Reg = abcd + + 0 abcd (reg ) | (mem & 0x00000000) + 1 bcd4 (reg << 8) | (mem & 0x000000ff) + 2 cd34 (reg << 16) | (mem & 0x0000ffff) + 3 d234 (reg << 24) | (mem & 0x00ffffff) + */ +} + +/********************************************************* +* Moves between GPR and COPx * +* Format: OP rt, fs * +*********************************************************/ +static void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } +static void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; } + +static INLINE void MTC0(int reg, u32 val) { + switch (reg) { + case 13: // Cause + psxRegs.CP0.n.Cause = val & ~(0xfc00); + + // the next code is untested, if u know please + // tell me if it works ok or not (linuzappz) + if (psxRegs.CP0.n.Cause & psxRegs.CP0.n.Status & 0x0300 && + psxRegs.CP0.n.Status & 0x1) { + psxException(psxRegs.CP0.n.Cause, 0); + } + break; + + default: + psxRegs.CP0.r[reg] = val; + break; + } +} + +static void psxMTC0() { MTC0(_Rd_, _u32(_rRt_)); } +static void psxCTC0() { MTC0(_Rd_, _u32(_rRt_)); } + +/********************************************************* +* Unknow instruction (would generate an exception) * +* Format: ? * +*********************************************************/ +static void psxNULL() { +#ifdef PSXCPU_LOG + PSXCPU_LOG("psx: Unimplemented op %x\n", psxRegs.code); +#endif +} + +static void psxSPECIAL() { + psxSPC[_Funct_](); +} + +static void psxREGIMM() { + psxREG[_Rt_](); +} + +static void psxCOP0() { + psxCP0[_Rs_](); +} + +static void psxHLE() { + psxHLEt[psxRegs.code & 0xff](); +} + +static void (*psxBSC[64])() = { + psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ, + psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI , + psxCOP0 , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxLB , psxLH , psxLWL , psxLW , psxLBU , psxLHU , psxLWR , psxNULL, + psxSB , psxSH , psxSWL , psxSW , psxNULL, psxNULL, psxSWR , psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxHLE , psxNULL, psxNULL, psxNULL, psxNULL +}; + + +static void (*psxSPC[64])() = { + psxSLL , psxNULL , psxSRL , psxSRA , psxSLLV , psxNULL , psxSRLV, psxSRAV, + psxJR , psxJALR , psxNULL, psxNULL, psxSYSCALL, psxBREAK, psxNULL, psxNULL, + psxMFHI, psxMTHI , psxMFLO, psxMTLO, psxNULL , psxNULL , psxNULL, psxNULL, + psxMULT, psxMULTU, psxDIV , psxDIVU, psxNULL , psxNULL , psxNULL, psxNULL, + psxADD , psxADDU , psxSUB , psxSUBU, psxAND , psxOR , psxXOR , psxNOR , + psxNULL, psxNULL , psxSLT , psxSLTU, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL, + psxNULL, psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, psxNULL +}; + +static void (*psxREG[32])() = { + psxBLTZ , psxBGEZ , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxBLTZAL, psxBGEZAL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + +static void (*psxCP0[32])() = { + psxMFC0, psxNULL, psxCFC0, psxNULL, psxMTC0, psxNULL, psxCTC0, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxRFE , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, + psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL +}; + + +/////////////////////////////////////////// + +static int intInit() { + return 0; +} + +static void intReset() { + branch=branch2=0; +} + +static void intExecute() { + for (;;) + { + if(!CounterSPURun()) + { + psxShutdown(); + return; + } + SPUendflush(); + execI(); + } +} + +static void intExecuteBlock() { + branch2 = 0; + while (!branch2) execI(); +} + +static void intClear(u32 Addr, u32 Size) { +} + +static void intShutdown() { +} + +R3000Acpu psxInt = { + intInit, + intReset, + intExecute, + intExecuteBlock, + intClear, + intShutdown +};