Skip to content

Commit

Permalink
EE/Int: Improve FPU emulation
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Nov 6, 2023
1 parent cd5a916 commit 65d4baa
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 14 deletions.
4 changes: 2 additions & 2 deletions pcsx2/COP2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
39 changes: 29 additions & 10 deletions pcsx2/FPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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)
Expand Down Expand Up @@ -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 ); \
}
Expand Down Expand Up @@ -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() {
Expand Down Expand Up @@ -281,7 +297,7 @@ void MADDA_S() {
}

void MAX_S() {
_FdValf_ = std::max( _FsValf_, _FtValf_ );
_FdValUl_ = fp_max( _FsValUl_, _FtValUl_ );
clearFPUFlags( FPUflagO | FPUflagU );
}

Expand All @@ -291,7 +307,7 @@ void MFC1() {
}

void MIN_S() {
_FdValf_ = std::min( _FsValf_, _FtValf_ );
_FdValUl_ = fp_min(_FsValUl_, _FtValUl_);
clearFPUFlags( FPUflagO | FPUflagU );
}

Expand Down Expand Up @@ -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
Expand All @@ -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() {
Expand Down
4 changes: 2 additions & 2 deletions pcsx2/VUops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions pcsx2/x86/microVU_Macro.inl
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,7 @@ void recSQC2()
}

#else
namespace Interp = R5900::Interpreter::OpcodeImpl;

REC_FUNC(LQC2);
REC_FUNC(SQC2);
Expand Down

0 comments on commit 65d4baa

Please sign in to comment.