mirror of https://github.com/PCSX2/pcsx2.git
EE/Int: Improve FPU emulation
This commit is contained in:
parent
cd5a916f99
commit
65d4baa944
|
@ -27,13 +27,13 @@ using namespace R5900::Interpreter;
|
|||
|
||||
//Run the FINISH either side of the VCALL's as we have no control over it past here.
|
||||
void VCALLMS() {
|
||||
vu0Finish();
|
||||
_vu0FinishMicro();
|
||||
vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF));
|
||||
//vif0Regs.stat.VEW = false;
|
||||
}
|
||||
|
||||
void VCALLMSR() {
|
||||
vu0Finish();
|
||||
_vu0FinishMicro();
|
||||
vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0]);
|
||||
//vif0Regs.stat.VEW = false;
|
||||
}
|
||||
|
|
|
@ -76,12 +76,14 @@
|
|||
// If we have an infinity value, then Overflow has occured.
|
||||
bool checkOverflow(u32& xReg, u32 cFlagsToSet)
|
||||
{
|
||||
if ( (xReg & ~0x80000000) == PosInfinity ) {
|
||||
if ((xReg & ~0x80000000) == PosInfinity) {
|
||||
/*Console.Warning( "FPU OVERFLOW!: Changing to +/-Fmax!!!!!!!!!!!!\n" );*/
|
||||
xReg = (xReg & 0x80000000) | posFmax;
|
||||
_ContVal_ |= (cFlagsToSet);
|
||||
return true;
|
||||
}
|
||||
else if (cFlagsToSet & FPUflagO)
|
||||
_ContVal_ &= ~FPUflagO;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -94,10 +96,22 @@ bool checkUnderflow(u32& xReg, u32 cFlagsToSet) {
|
|||
_ContVal_ |= (cFlagsToSet);
|
||||
return true;
|
||||
}
|
||||
else if (cFlagsToSet & FPUflagU)
|
||||
_ContVal_ &= ~FPUflagU;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
__fi u32 fp_max(u32 a, u32 b)
|
||||
{
|
||||
return ((s32)a < 0 && (s32)b < 0) ? std::min<s32>(a, b) : std::max<s32>(a, b);
|
||||
}
|
||||
|
||||
__fi u32 fp_min(u32 a, u32 b)
|
||||
{
|
||||
return ((s32)a < 0 && (s32)b < 0) ? std::max<s32>(a, b) : std::min<s32>(a, b);
|
||||
}
|
||||
|
||||
/* Checks if Divide by Zero will occur. (z/y = x)
|
||||
cFlagsToSet1 = Flags to set if (z != 0)
|
||||
cFlagsToSet2 = Flags to set if (z == 0)
|
||||
|
@ -137,7 +151,7 @@ bool checkDivideByZero(u32& xReg, u32 yDivisorReg, u32 zDividendReg, u32 cFlagsT
|
|||
#else
|
||||
// Used for Comparing; This compares if the floats are exactly the same.
|
||||
#define C_cond_S(cond) { \
|
||||
_ContVal_ = ( _FsValf_ cond _FtValf_ ) ? \
|
||||
_ContVal_ = ( fpuDouble(_FsValUl_) cond fpuDouble(_FtValUl_) ) ? \
|
||||
( _ContVal_ | FPUflagC ) : \
|
||||
( _ContVal_ & ~FPUflagC ); \
|
||||
}
|
||||
|
@ -231,12 +245,14 @@ void C_LT() {
|
|||
}
|
||||
|
||||
void CFC1() {
|
||||
if ( !_Rt_ ) return;
|
||||
if (!_Rt_) return;
|
||||
|
||||
if (_Fs_ >= 16)
|
||||
if (_Fs_ == 31)
|
||||
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)fpuRegs.fprc[31]; // force sign extension to 64 bit
|
||||
else if (_Fs_ == 0)
|
||||
cpuRegs.GPR.r[_Rt_].SD[0] = 0x2E00;
|
||||
else
|
||||
cpuRegs.GPR.r[_Rt_].SD[0] = (s32)fpuRegs.fprc[0]; // force sign extension to 64 bit
|
||||
cpuRegs.GPR.r[_Rt_].SD[0] = 0;
|
||||
}
|
||||
|
||||
void CTC1() {
|
||||
|
@ -281,7 +297,7 @@ void MADDA_S() {
|
|||
}
|
||||
|
||||
void MAX_S() {
|
||||
_FdValf_ = std::max( _FsValf_, _FtValf_ );
|
||||
_FdValUl_ = fp_max( _FsValUl_, _FtValUl_ );
|
||||
clearFPUFlags( FPUflagO | FPUflagU );
|
||||
}
|
||||
|
||||
|
@ -291,7 +307,7 @@ void MFC1() {
|
|||
}
|
||||
|
||||
void MIN_S() {
|
||||
_FdValf_ = std::min( _FsValf_, _FtValf_ );
|
||||
_FdValUl_ = fp_min(_FsValUl_, _FtValUl_);
|
||||
clearFPUFlags( FPUflagO | FPUflagU );
|
||||
}
|
||||
|
||||
|
@ -336,9 +352,11 @@ void NEG_S() {
|
|||
|
||||
void RSQRT_S() {
|
||||
FPRreg temp;
|
||||
clearFPUFlags(FPUflagD | FPUflagI);
|
||||
|
||||
if ( ( _FtValUl_ & 0x7F800000 ) == 0 ) { // Ft is zero (Denormals are Zero)
|
||||
_ContVal_ |= FPUflagD | FPUflagSD;
|
||||
_FdValUl_ = ( ( _FsValUl_ ^ _FtValUl_ ) & 0x80000000 ) | posFmax;
|
||||
_FdValUl_ = ( _FtValUl_ & 0x80000000 ) | posFmax;
|
||||
return;
|
||||
}
|
||||
else if ( _FtValUl_ & 0x80000000 ) { // Ft is negative
|
||||
|
@ -353,14 +371,15 @@ void RSQRT_S() {
|
|||
}
|
||||
|
||||
void SQRT_S() {
|
||||
clearFPUFlags(FPUflagI | FPUflagD);
|
||||
|
||||
if ( ( _FtValUl_ & 0x7F800000 ) == 0 ) // If Ft = +/-0
|
||||
_FdValUl_ = 0;// result is 0
|
||||
_FdValUl_ = _FtValUl_ & 0x80000000;// result is 0
|
||||
else if ( _FtValUl_ & 0x80000000 ) { // If Ft is Negative
|
||||
_ContVal_ |= FPUflagI | FPUflagSI;
|
||||
_FdValf_ = sqrt( fabs( fpuDouble( _FtValUl_ ) ) );
|
||||
} else
|
||||
_FdValf_ = sqrt( fpuDouble( _FtValUl_ ) ); // If Ft is Positive
|
||||
clearFPUFlags( FPUflagD );
|
||||
}
|
||||
|
||||
void SUB_S() {
|
||||
|
|
|
@ -4692,7 +4692,7 @@ _vuRegsTables(VU1, VU1regs, Fnptr_VuRegsN)
|
|||
|
||||
static __fi void SYNCMSFLAGS()
|
||||
{
|
||||
VU0.VI[REG_STATUS_FLAG].UL = (VU0.VI[REG_STATUS_FLAG].UL & 0xC30) | (VU0.statusflag & 0xF) | ((VU0.statusflag & 0xF) << 6);
|
||||
VU0.VI[REG_STATUS_FLAG].UL = (VU0.VI[REG_STATUS_FLAG].UL & 0xFC0) | (VU0.statusflag & 0xF) | ((VU0.statusflag & 0xF) << 6);
|
||||
VU0.VI[REG_MAC_FLAG].UL = VU0.macflag;
|
||||
}
|
||||
|
||||
|
@ -4703,7 +4703,7 @@ static __fi void SYNCCLIPFLAG()
|
|||
|
||||
static __fi void SYNCSTATUSFLAG()
|
||||
{
|
||||
VU0.VI[REG_STATUS_FLAG].UL = (VU0.VI[REG_STATUS_FLAG].UL & 0x3F) | (VU0.statusflag & 0xFC0);
|
||||
VU0.VI[REG_STATUS_FLAG].UL = (VU0.VI[REG_STATUS_FLAG].UL & 0xFC0) | (VU0.statusflag & 0xF) | ((VU0.statusflag & 0xF) << 6);
|
||||
}
|
||||
|
||||
static __fi void SYNCFDIV()
|
||||
|
|
|
@ -890,6 +890,7 @@ void recSQC2()
|
|||
}
|
||||
|
||||
#else
|
||||
namespace Interp = R5900::Interpreter::OpcodeImpl;
|
||||
|
||||
REC_FUNC(LQC2);
|
||||
REC_FUNC(SQC2);
|
||||
|
|
Loading…
Reference in New Issue