Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EE/Int: Improve FPU emulation #10222

Merged
merged 1 commit into from
Nov 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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