mirror of https://github.com/PCSX2/pcsx2.git
175 lines
5.3 KiB
C
175 lines
5.3 KiB
C
/* 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 <math.h>
|
|
#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
|