Skip to content

Commit 179a4de

Browse files
[Soft-Float] - Fixes a VU underflow flag edge case and apply some code recommandations.
In some cases, a Zero value could have it's underflow flag skipped, this is fixed. We also start to simplify the code a bit per recommandations done in the pull request.
1 parent 11e913d commit 179a4de

File tree

4 files changed

+22
-104
lines changed

4 files changed

+22
-104
lines changed

pcsx2/FPU.cpp

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -338,33 +338,27 @@ void CTC1() {
338338
}
339339

340340
void CVT_S() {
341-
if (CHECK_FPU_SOFT_ADDSUB || CHECK_FPU_SOFT_MUL || CHECK_FPU_SOFT_DIVSQRT) { _FdValUl_ = PS2Float::Itof(0, _FsValSl_).raw; }
342-
else
343-
{
344-
_FdValf_ = (float)_FsValSl_;
345-
_FdValf_ = fpuDouble(_FdValUl_);
346-
}
341+
_FdValf_ = (float)_FsValSl_;
342+
_FdValf_ = fpuDouble(_FdValUl_);
347343
}
348344

349345
void CVT_W() {
350-
if (CHECK_FPU_SOFT_ADDSUB || CHECK_FPU_SOFT_MUL || CHECK_FPU_SOFT_DIVSQRT) { _FdValSl_ = PS2Float::Ftoi(0, _FsValUl_); }
351-
else if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValSl_ = (s32)_FsValf_; }
346+
if ( ( _FsValUl_ & 0x7F800000 ) <= 0x4E800000 ) { _FdValSl_ = (s32)_FsValf_; }
352347
else if ( ( _FsValUl_ & 0x80000000 ) == 0 ) { _FdValUl_ = 0x7fffffff; }
353348
else { _FdValUl_ = 0x80000000; }
354349
}
355350

356351
void DIV_S() {
357-
if (CHECK_FPU_SOFT_DIVSQRT)
352+
if (checkDivideByZero( _FdValUl_, _FtValUl_, _FsValUl_, FPUflagD | FPUflagSD, FPUflagI | FPUflagSI)) return;
353+
else if (CHECK_FPU_SOFT_DIVSQRT)
358354
{
359355
PS2Float divres = fpuAccurateDiv(_FsValUl_, _FtValUl_);
360356
_FdValUl_ = divres.raw;
361-
if (checkDivideByZeroInvalidSoft(divres, FPUflagD | FPUflagSD, FPUflagI | FPUflagSI)) return;
362357
if (checkOverflowUnderflowSoft(divres, FPUflagO | FPUflagSO, true)) return;
363358
checkOverflowUnderflowSoft(divres, FPUflagU | FPUflagSU, false);
364359
}
365360
else
366361
{
367-
if (checkDivideByZero( _FdValUl_, _FtValUl_, _FsValUl_, FPUflagD | FPUflagSD, FPUflagI | FPUflagSI)) return;
368362
_FdValf_ = fpuDouble( _FsValUl_ ) / fpuDouble( _FtValUl_ );
369363
if (checkOverflow( _FdValUl_, 0)) return;
370364
checkUnderflow( _FdValUl_, 0);

pcsx2/PS2Float.cpp

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -666,85 +666,6 @@ PS2Float PS2Float::DoMul(PS2Float other)
666666
return PS2Float(sign | (u32)(resExponent << MANTISSA_BITS) | (resMantissa & 0x7FFFFF));
667667
}
668668

669-
PS2Float PS2Float::Itof(s32 complement, s32 f1)
670-
{
671-
if (f1 == 0)
672-
return PS2Float(0);
673-
674-
s32 resExponent;
675-
676-
bool negative = f1 < 0;
677-
678-
if (f1 == -2147483648)
679-
{
680-
if (complement <= 0)
681-
// special case
682-
return PS2Float(0xcf000000);
683-
else
684-
f1 = 2147483647;
685-
}
686-
687-
s32 u = std::abs(f1);
688-
689-
s32 shifts;
690-
691-
s32 lzcnt = Common::CountLeadingSignBits(u);
692-
if (lzcnt < 8)
693-
{
694-
s32 count = 8 - lzcnt;
695-
u >>= count;
696-
shifts = -count;
697-
}
698-
else
699-
{
700-
s32 count = lzcnt - 8;
701-
u <<= count;
702-
shifts = count;
703-
}
704-
705-
resExponent = BIAS + MANTISSA_BITS - shifts - complement;
706-
707-
if (resExponent >= 158)
708-
return negative ? PS2Float(0xcf000000) : PS2Float(0x4f000000);
709-
else if (resExponent >= 0)
710-
return PS2Float(negative, (u8)resExponent, (u32)u);
711-
712-
return PS2Float(0);
713-
}
714-
715-
s32 PS2Float::Ftoi(s32 complement, u32 f1)
716-
{
717-
u32 a, result;
718-
719-
a = f1;
720-
if ((f1 & 0x7F800000) == 0)
721-
result = 0;
722-
else
723-
{
724-
complement = (s32)(f1 >> MANTISSA_BITS & 0xFF) + complement;
725-
f1 &= 0x7FFFFF;
726-
f1 |= 0x800000;
727-
if (complement < 158)
728-
{
729-
if (complement > 126)
730-
{
731-
f1 = (f1 << 7) >> (31 - ((u8)complement - 126));
732-
if ((s32)a < 0)
733-
f1 = ~f1 + 1;
734-
result = f1;
735-
}
736-
else
737-
result = 0;
738-
}
739-
else if ((s32)a < 0)
740-
result = SIGNMASK;
741-
else
742-
result = MAX_FLOATING_POINT_VALUE;
743-
}
744-
745-
return (s32)result;
746-
}
747-
748669
u8 PS2Float::Clip(u32 f1, u32 f2, bool& cplus, bool& cminus)
749670
{
750671
bool resultPlus = false;

pcsx2/PS2Float.h

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,21 @@ class PS2Float
2525
constexpr u8 Exponent() const { return (raw >> 23) & 0xFF; }
2626
constexpr bool Sign() const { return ((raw >> 31) & 1) != 0; }
2727

28-
PS2Float(s32 value);
28+
__fi PS2Float(s32 value);
2929

30-
PS2Float(u32 value);
30+
__fi PS2Float(u32 value);
3131

32-
PS2Float(float value);
32+
__fi PS2Float(float value);
3333

34-
PS2Float(bool sign, u8 exponent, u32 mantissa);
34+
__fi PS2Float(bool sign, u8 exponent, u32 mantissa);
3535

36-
static PS2Float Max();
36+
__fi static PS2Float Max();
3737

38-
static PS2Float Min();
38+
__fi static PS2Float Min();
3939

40-
static PS2Float One();
40+
__fi static PS2Float One();
4141

42-
static PS2Float MinOne();
43-
44-
static PS2Float Itof(s32 complement, s32 f1);
45-
46-
static s32 Ftoi(s32 complement, u32 f1);
42+
__fi static PS2Float MinOne();
4743

4844
static u8 Clip(u32 f1, u32 f2, bool& cplus, bool& cminus);
4945

pcsx2/VUflags.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,21 +49,28 @@ static __ri u32 VU_MAC_UPDATE( s32 shift, VURegs* VU, float f)
4949

5050
static __ri u32 VU_MAC_UPDATE(s32 shift, VURegs* VU, PS2Float f)
5151
{
52+
bool isUnderflow = false;
53+
5254
u32 v = f.raw;
5355

5456
if (v & PS2Float::SIGNMASK)
5557
VU->macflag |= 0x0010 << shift;
5658
else
5759
VU->macflag &= ~(0x0010 << shift);
60+
61+
if (f.uf)
62+
{
63+
isUnderflow = true;
64+
VU->macflag = (VU->macflag & ~(0x1000 << shift)) | (0x0101 << shift);
65+
}
5866

5967
if (f.IsZero())
6068
{
6169
VU->macflag = (VU->macflag & ~(0x1100 << shift)) | (0x0001 << shift);
6270
return v;
6371
}
64-
else if (f.uf) { VU->macflag = (VU->macflag & ~(0x1000 << shift)) | (0x0101 << shift); }
6572
else if (f.of) { VU->macflag = (VU->macflag & ~(0x0101 << shift)) | (0x1000 << shift); }
66-
else { VU->macflag = (VU->macflag & ~(0x1101 << shift)); }
73+
else if (!isUnderflow) { VU->macflag = (VU->macflag & ~(0x1101 << shift)); }
6774

6875
return v;
6976
}

0 commit comments

Comments
 (0)