Files
archived-pcsx2/pcsx2/R3000AOpcodeTables.cpp
Jake.Stine 377830b3a9 IOP Fixes/Optimizations:
* Fixed the IOP's recExecute so that it correctly preserves X86 registers (EDI and EBX were not preserved!)
 * Optimized the recExecute procedure, seems like a nice speedup in FMVs and some games that are IOP intensive.
 * Renamed psxMemRead to iopMemRead, added new Virt/Phys functions, and fixed several instances of DMAs using translated addresses (DMAs are always physical maps).  Our IOP doesn't really emulate the tlb so it won't fix anything, but it's more correct in cas stuff is better supported in the future.
 * Removed unneeded FreezeMMXRegs, since the IOPrec doesn't use any mmx/xmm regs anyway.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@628 96395faa-99c1-11dd-bbfe-3dabce05a288
2009-02-27 18:12:59 +00:00

384 lines
13 KiB
C++

/* Pcsx2 - Pc Ps2 Emulator
* Copyright (C) 2002-2009 Pcsx2 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 "PrecompiledHeader.h"
#include "PsxCommon.h"
#include "Common.h"
extern void zeroEx();
// Note: Branch instructions of the Interpreter are defined externally because
// the recompiler shouldn't be using them (it isn't entirely safe, due to the
// delay slot and event handling differences between recs and ints)
void psxBGEZ();
void psxBGEZAL();
void psxBGTZ();
void psxBLEZ();
void psxBLTZ();
void psxBLTZAL();
void psxBEQ();
void psxBNE();
void psxJ();
void psxJAL();
void psxJR();
void psxJALR();
/*********************************************************
* Arithmetic with immediate operand *
* Format: OP rt, rs, immediate *
*********************************************************/
void psxADDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) + _Imm_ ; } // Rt = Rs + Im (Exception on Integer Overflow)
void psxADDIU() { // Rt = Rs + Im
if (!_Rt_)
{
zeroEx();
return;
}
_rRt_ = _u32(_rRs_) + _Imm_ ;
}
void psxANDI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) & _ImmU_; } // Rt = Rs And Im
void psxORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) | _ImmU_; } // Rt = Rs Or Im
void psxXORI() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) ^ _ImmU_; } // Rt = Rs Xor Im
void psxSLTI() { if (!_Rt_) return; _rRt_ = _i32(_rRs_) < _Imm_ ; } // Rt = Rs < Im (Signed)
void psxSLTIU() { if (!_Rt_) return; _rRt_ = _u32(_rRs_) < _ImmU_; } // Rt = Rs < Im (Unsigned)
/*********************************************************
* Register arithmetic *
* Format: OP rd, rs, rt *
*********************************************************/
void psxADD() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt (Exception on Integer Overflow)
void psxADDU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) + _u32(_rRt_); } // Rd = Rs + Rt
void psxSUB() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt (Exception on Integer Overflow)
void psxSUBU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) - _u32(_rRt_); } // Rd = Rs - Rt
void psxAND() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) & _u32(_rRt_); } // Rd = Rs And Rt
void psxOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) | _u32(_rRt_); } // Rd = Rs Or Rt
void psxXOR() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) ^ _u32(_rRt_); } // Rd = Rs Xor Rt
void psxNOR() { if (!_Rd_) return; _rRd_ =~(_u32(_rRs_) | _u32(_rRt_)); }// Rd = Rs Nor Rt
void psxSLT() { if (!_Rd_) return; _rRd_ = _i32(_rRs_) < _i32(_rRt_); } // Rd = Rs < Rt (Signed)
void psxSLTU() { if (!_Rd_) return; _rRd_ = _u32(_rRs_) < _u32(_rRt_); } // Rd = Rs < Rt (Unsigned)
/*********************************************************
* Register mult/div & Register trap logic *
* Format: OP rs, rt *
*********************************************************/
void psxDIV() {
if (_rRt_ != 0) {
_rLo_ = _i32(_rRs_) / _i32(_rRt_);
_rHi_ = _i32(_rRs_) % _i32(_rRt_);
}
}
void psxDIVU() {
if (_rRt_ != 0) {
_rLo_ = _rRs_ / _rRt_;
_rHi_ = _rRs_ % _rRt_;
}
}
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);
}
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);
}
/*********************************************************
* Shift arithmetic with constant shift *
* Format: OP rd, rt, sa *
*********************************************************/
void psxSLL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _Sa_; } // Rd = Rt << sa
void psxSRA() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (arithmetic)
void psxSRL() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) >> _Sa_; } // Rd = Rt >> sa (logical)
/*********************************************************
* Shift arithmetic with variant register shift *
* Format: OP rd, rt, rs *
*********************************************************/
void psxSLLV() { if (!_Rd_) return; _rRd_ = _u32(_rRt_) << _u32(_rRs_); } // Rd = Rt << rs
void psxSRAV() { if (!_Rd_) return; _rRd_ = _i32(_rRt_) >> _u32(_rRs_); } // Rd = Rt >> rs (arithmetic)
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 *
*********************************************************/
void psxLUI() { if (!_Rt_) return; _rRt_ = psxRegs.code << 16; } // Upper halfword of Rt = Im
/*********************************************************
* Move from HI/LO to GPR *
* Format: OP rd *
*********************************************************/
void psxMFHI() { if (!_Rd_) return; _rRd_ = _rHi_; } // Rd = Hi
void psxMFLO() { if (!_Rd_) return; _rRd_ = _rLo_; } // Rd = Lo
/*********************************************************
* Move to GPR to HI/LO & Register jump *
* Format: OP rs *
*********************************************************/
void psxMTHI() { _rHi_ = _rRs_; } // Hi = Rs
void psxMTLO() { _rLo_ = _rRs_; } // Lo = Rs
/*********************************************************
* Special purpose instructions *
* Format: OP *
*********************************************************/
void psxBREAK() {
// Break exception - psx rom doens't handles this
psxRegs.pc -= 4;
psxException(0x24, iopIsDelaySlot);
}
void psxSYSCALL() {
psxRegs.pc -= 4;
psxException(0x20, iopIsDelaySlot);
}
void psxRFE() {
// SysPrintf("RFE\n");
psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
((psxRegs.CP0.n.Status & 0x3c) >> 2);
// Log=0;
}
/*********************************************************
* Load and store for GPR *
* Format: OP rt, offset(base) *
*********************************************************/
#define _oB_ (_u32(_rRs_) + _Imm_)
void psxLB() {
if (_Rt_) {
_rRt_ = (s8 )iopMemRead8(_oB_);
} else {
iopMemRead8(_oB_);
}
}
void psxLBU() {
if (_Rt_) {
_rRt_ = iopMemRead8(_oB_);
} else {
iopMemRead8(_oB_);
}
}
void psxLH() {
if (_Rt_) {
_rRt_ = (s16)iopMemRead16(_oB_);
} else {
iopMemRead16(_oB_);
}
}
void psxLHU() {
if (_Rt_) {
_rRt_ = iopMemRead16(_oB_);
} else {
iopMemRead16(_oB_);
}
}
void psxLW() {
if (_Rt_) {
_rRt_ = iopMemRead32(_oB_);
} else {
iopMemRead32(_oB_);
}
}
void psxLWL() {
u32 shift = (_oB_ & 3) << 3;
u32 mem = iopMemRead32(_oB_ & 0xfffffffc);
if (!_Rt_) return;
_rRt_ = ( _u32(_rRt_) & (0x00ffffff >> shift) ) |
( mem << (24 - 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)
*/
}
void psxLWR() {
u32 shift = (_oB_ & 3) << 3;
u32 mem = iopMemRead32(_oB_ & 0xfffffffc);
if (!_Rt_) return;
_rRt_ = ( _u32(_rRt_) & (0xffffff00 << (24 - shift)) ) |
( mem >> 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)
*/
}
void psxSB() { iopMemWrite8 (_oB_, _u8 (_rRt_)); }
void psxSH() { iopMemWrite16(_oB_, _u16(_rRt_)); }
void psxSW() { iopMemWrite32(_oB_, _u32(_rRt_)); }
void psxSWL() {
u32 shift = (_oB_ & 3) << 3;
u32 mem = iopMemRead32(_oB_ & 0xfffffffc);
iopMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) >> (24 - shift) ) ) |
( mem & (0xffffff00 << 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)
*/
}
void psxSWR() {
u32 shift = (_oB_ & 3) << 3;
u32 mem = iopMemRead32(_oB_ & 0xfffffffc);
iopMemWrite32((_oB_ & 0xfffffffc), ( ( _u32(_rRt_) << shift ) |
(mem & (0x00ffffff >> (24 - 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 *
*********************************************************/
void psxMFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; }
void psxCFC0() { if (!_Rt_) return; _rRt_ = (int)_rFs_; }
void psxMTC0() { _rFs_ = _u32(_rRt_); }
void psxCTC0() { _rFs_ = _u32(_rRt_); }
/*********************************************************
* Unknow instruction (would generate an exception) *
* Format: ? *
*********************************************************/
void psxNULL() {
SysPrintf("psx: Unimplemented op %x\n", psxRegs.code);
}
void psxSPECIAL() {
psxSPC[_Funct_]();
}
void psxREGIMM() {
psxREG[_Rt_]();
}
void psxCOP0() {
psxCP0[_Rs_]();
}
void psxCOP2() {
psxCP2[_Funct_]();
}
void psxBASIC() {
psxCP2BSC[_Rs_]();
}
void (*psxBSC[64])() = {
psxSPECIAL, psxREGIMM, psxJ , psxJAL , psxBEQ , psxBNE , psxBLEZ, psxBGTZ,
psxADDI , psxADDIU , psxSLTI, psxSLTIU, psxANDI, psxORI , psxXORI, psxLUI ,
psxCOP0 , psxNULL , psxCOP2, 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, psxNULL , psxNULL, psxNULL, psxNULL, psxNULL
};
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
};
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
};
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
};
void (*psxCP2[64])() = {
psxBASIC, psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL, psxNULL, // 00
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 08
psxNULL , psxNULL, psxNULL, psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 10
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL , psxNULL , psxNULL , psxNULL, // 18
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 20
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, // 28
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL, // 30
psxNULL , psxNULL , psxNULL , psxNULL, psxNULL, psxNULL , psxNULL , psxNULL // 38
};
void (*psxCP2BSC[32])() = {
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL,
psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL, psxNULL
};