/* Pcsx2 - Pc Ps2 Emulator * Copyright (C) 2002-2003 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "Common.h" #include "R5900.h" #include "InterTables.h" // Helper Macros //**************************************************************** #define _Ft_ ( ( cpuRegs.code >> 16 ) & 0x1F ) #define _Fs_ ( ( cpuRegs.code >> 11 ) & 0x1F ) #define _Fd_ ( ( cpuRegs.code >> 6 ) & 0x1F ) #define _FtValf_ fpuRegs.fpr[ _Ft_ ].f #define _FsValf_ fpuRegs.fpr[ _Fs_ ].f #define _FdValf_ fpuRegs.fpr[ _Fd_ ].f #define _FAValf_ fpuRegs.ACC.f #define _ContVal_ fpuRegs.fprc[ 31 ] // Testing #define _FtValUl_ fpuRegs.fpr[ _Ft_ ].UL #define _FsValUl_ fpuRegs.fpr[ _Fs_ ].UL #define _FdValUl_ fpuRegs.fpr[ _Fd_ ].UL #define _FAValUl_ fpuRegs.ACC.UL //**************************************************************** void COP1() { #ifdef FPU_LOG FPU_LOG("%s\n", disR5900F(cpuRegs.code, cpuRegs.pc)); #endif Int_COP1PrintTable[_Rs_](); } /********************************************************* * Load and store for COP1 * * Format: OP rt, offset(base) * *********************************************************/ void LWC1() { s32 addr; addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);// ((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); memRead32(addr, &fpuRegs.fpr[_Rt_].UL); } void SWC1() { s32 addr; addr = cpuRegs.GPR.r[_Rs_].UL[0] + (s16)(cpuRegs.code);//((cpuRegs.code & 0x8000 ? 0xFFFF8000 : 0)| (cpuRegs.code & 0x7fff)); memWrite32(addr, fpuRegs.fpr[_Rt_].UL); } void COP1_BC1() { Int_COP1BC1PrintTable[_Rt_](); } void COP1_S() { Int_COP1SPrintTable[_Funct_](); } void COP1_W() { Int_COP1WPrintTable[_Funct_](); } void COP1_Unknown() { #ifdef FPU_LOG FPU_LOG("Unknown FPU opcode called\n"); #endif } void MFC1() { if ( !_Rt_ ) return; cpuRegs.GPR.r[_Rt_].UD[0] = (s32)_FsValUl_; } void CFC1() { if ( !_Rt_ || ( _Fs_ != 0 && _Fs_ != 31 ) ) return; cpuRegs.GPR.r[_Rt_].UD[0] = (s32)fpuRegs.fprc[_Fs_]; } void MTC1() { _FsValUl_ = cpuRegs.GPR.r[_Rt_].UL[0]; } void CTC1() { if(_Fs_!=31) return; fpuRegs.fprc[_Fs_] = cpuRegs.GPR.r[_Rt_].UL[0]; } #define C_cond_S(cond) \ _ContVal_ = ( _FsValf_ cond _FtValf_ ) ? \ ( _ContVal_ | 0x00800000 ) : \ ( _ContVal_ & ~0x00800000 ); void C_F() { _ContVal_ &= ~0x00800000;} //clears C regardless void C_EQ() { C_cond_S(==); } void C_LT() { C_cond_S(<); } void C_LE() { C_cond_S(<=); } #define BC1(cond) \ if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ intDoBranch( _BranchTarget_ ); \ } void BC1F() { BC1(==); } void BC1T() { BC1(!=); } #define BC1L(cond) \ if ( ( _ContVal_ & 0x00800000 ) cond 0 ) { \ intDoBranch( _BranchTarget_ ); \ } else cpuRegs.pc += 4; void BC1FL() { BC1L(==); } // Equal to 0 void BC1TL() { BC1L(!=); } // different from 0 void ADD_S() { _FdValf_ = _FsValf_ + _FtValf_; } void SUB_S() { _FdValf_ = _FsValf_ - _FtValf_; } void MUL_S() { _FdValf_ = _FsValf_ * _FtValf_; } void MOV_S() { _FdValf_ = _FsValf_; } void NEG_S() { _FdValf_ = -_FsValf_; } void ADDA_S() { _FAValf_ = _FsValf_ + _FtValf_; } void SUBA_S() { _FAValf_ = _FsValf_ - _FtValf_; } void MULA_S() { _FAValf_ = _FsValf_ * _FtValf_; } void MADD_S() { _FdValf_ = _FAValf_ + ( _FsValf_ * _FtValf_ ); } void MSUB_S() { _FdValf_ = _FAValf_ - ( _FsValf_ * _FtValf_ ); } void MADDA_S() { _FAValf_ += _FsValf_ * _FtValf_; } void MSUBA_S() { _FAValf_ -= _FsValf_ * _FtValf_; } void ABS_S() { _FdValf_ = fpufabsf(_FsValf_); } void MAX_S() { _FdValf_ = max( _FsValf_, _FtValf_ ); } void MIN_S() { _FdValf_ = min( _FsValf_, _FtValf_ ); } void DIV_S() { if ( _FtValf_ ) { _FdValf_ = _FsValf_ / _FtValf_; } } void SQRT_S() { //if ( _FtValf_ >= 0.0f ) { _FdValf_ = fpusqrtf( _FtValf_ ); } //else { _FdValf_ = fpusqrtf(fpufabsf(_FtValf_)); //} } void CVT_S() { _FdValf_ = (float)(s32)_FsValUl_; } void CVT_W() { if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValUl_ = (s32)(float)_FsValf_; } else if ( _FsValUl_ & 0x80000000 ) { _FdValUl_ = 0x80000000; } else { _FdValUl_ = 0x7fffffff; } } void RSQRT_S() { if ( _FtValf_ >= 0.0f ) { float tmp = fpusqrtf( _FtValf_ ); if ( tmp != 0 ) { _FdValf_ = _FsValf_ / tmp; } } } //3322 2222 2222 1111 1111 1100 0000 0000 //1098 7654 3210 9876 5432 1098 7654 3210 //0000 0000 0000 0000 0000 0000 0000 0000