mirror of https://github.com/PCSX2/pcsx2.git
[Soft-Float] - Improves the PS2Float class by using a raw float to speed-up simple calculations.
This greatly improves performance while using Soft-Floats.
This commit is contained in:
parent
8bc2ed9282
commit
745e4746fc
|
@ -146,16 +146,13 @@ bool checkDivideByZero(u32& xReg, u32 yDivisorReg, u32 zDividendReg, u32 cFlagsT
|
|||
|
||||
_ContVal_ |= dividendZero ? cFlagsToSet2 : cFlagsToSet1;
|
||||
|
||||
bool IsSigned = yMatrix.Sign ^ zMatrix.Sign;
|
||||
bool IsSigned = yMatrix.Sign() ^ zMatrix.Sign();
|
||||
|
||||
if (dividendZero)
|
||||
xReg = IsSigned ? PS2Float::MIN_FLOATING_POINT_VALUE : PS2Float::MAX_FLOATING_POINT_VALUE;
|
||||
else
|
||||
{
|
||||
PS2Float zeroRes = PS2Float(0);
|
||||
|
||||
zeroRes.Sign = IsSigned;
|
||||
xReg = zeroRes.AsUInt32();
|
||||
xReg = PS2Float(IsSigned, 0, 0).raw;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -221,28 +218,28 @@ float fpuDouble(u32 f)
|
|||
|
||||
static __fi u32 fpuAccurateAdd(u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_FPU_SOFT_ADDSUB) return PS2Float(a).Add(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_FPU_SOFT_ADDSUB) return PS2Float(a).Add(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(fpuDouble(a) + fpuDouble(b));
|
||||
}
|
||||
|
||||
static __fi u32 fpuAccurateSub(u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_FPU_SOFT_ADDSUB) return PS2Float(a).Sub(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_FPU_SOFT_ADDSUB) return PS2Float(a).Sub(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(fpuDouble(a) - fpuDouble(b));
|
||||
}
|
||||
|
||||
static __fi u32 fpuAccurateMul(u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_FPU_SOFT_MULDIV) return PS2Float(a).Mul(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_FPU_SOFT_MULDIV) return PS2Float(a).Mul(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(fpuDouble(a) * fpuDouble(b));
|
||||
}
|
||||
|
||||
static __fi u32 fpuAccurateDiv(u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_FPU_SOFT_MULDIV) return PS2Float(a).Div(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_FPU_SOFT_MULDIV) return PS2Float(a).Div(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(fpuDouble(a) / fpuDouble(b));
|
||||
}
|
||||
|
@ -472,17 +469,17 @@ void RSQRT_S() {
|
|||
if (value.IsDenormalized())
|
||||
{
|
||||
_ContVal_ |= FPUflagD | FPUflagSD;
|
||||
_FdValUl_ = value.Sign ? PS2Float::MIN_FLOATING_POINT_VALUE : PS2Float::MAX_FLOATING_POINT_VALUE;
|
||||
_FdValUl_ = value.Sign() ? PS2Float::MIN_FLOATING_POINT_VALUE : PS2Float::MAX_FLOATING_POINT_VALUE;
|
||||
return;
|
||||
}
|
||||
else if (_FtValUl_ & 0x80000000) // Ft is negative
|
||||
{
|
||||
_ContVal_ |= FPUflagI | FPUflagSI;
|
||||
_FdValUl_ = PS2Float(_FsValUl_).Rsqrt(PS2Float(value.Abs())).AsUInt32();
|
||||
_FdValUl_ = PS2Float(_FsValUl_).Rsqrt(PS2Float(value.Abs())).raw;
|
||||
}
|
||||
else // Ft is positive and not zero
|
||||
{
|
||||
_FdValUl_ = PS2Float(_FsValUl_).Rsqrt(value).AsUInt32();
|
||||
_FdValUl_ = PS2Float(_FsValUl_).Rsqrt(value).raw;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -519,10 +516,10 @@ void SQRT_S() {
|
|||
if (_FtValUl_ & 0x80000000) // If Ft is Negative
|
||||
{
|
||||
_ContVal_ |= FPUflagI | FPUflagSI;
|
||||
_FdValUl_ = PS2Float(value.Abs()).Sqrt().AsUInt32();
|
||||
_FdValUl_ = PS2Float(value.Abs()).Sqrt().raw;
|
||||
}
|
||||
else
|
||||
_FdValUl_ = value.Sqrt().AsUInt32(); // If Ft is Positive
|
||||
_FdValUl_ = value.Sqrt().raw; // If Ft is Positive
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -74,18 +74,14 @@ u64 PS2Float::MulMantissa(u32 a, u32 b)
|
|||
// Float Processor
|
||||
//****************************************************************
|
||||
|
||||
PS2Float::PS2Float(u32 value)
|
||||
: Sign((value >> 31) & 1)
|
||||
, Exponent((u8)(((value >> 23) & 0xFF)))
|
||||
, Mantissa(value & 0x7FFFFF)
|
||||
{
|
||||
}
|
||||
PS2Float::PS2Float(u32 value) { raw = value; }
|
||||
|
||||
PS2Float::PS2Float(bool sign, u8 exponent, u32 mantissa)
|
||||
: Sign(sign)
|
||||
, Exponent(exponent)
|
||||
, Mantissa(mantissa)
|
||||
{
|
||||
raw = 0;
|
||||
raw |= (sign ? 1u : 0u) << 31;
|
||||
raw |= (u32)(exponent << 23);
|
||||
raw |= mantissa;
|
||||
}
|
||||
|
||||
PS2Float PS2Float::Max()
|
||||
|
@ -108,15 +104,6 @@ PS2Float PS2Float::MinOne()
|
|||
return PS2Float(MIN_ONE);
|
||||
}
|
||||
|
||||
u32 PS2Float::AsUInt32() const
|
||||
{
|
||||
u32 result = 0;
|
||||
result |= (Sign ? 1u : 0u) << 31;
|
||||
result |= (u32)(Exponent << 23);
|
||||
result |= Mantissa;
|
||||
return result;
|
||||
}
|
||||
|
||||
PS2Float PS2Float::Add(PS2Float addend)
|
||||
{
|
||||
if (IsDenormalized() || addend.IsDenormalized())
|
||||
|
@ -125,8 +112,8 @@ PS2Float PS2Float::Add(PS2Float addend)
|
|||
if (IsAbnormal() && addend.IsAbnormal())
|
||||
return SolveAbnormalAdditionOrSubtractionOperation(*this, addend, true);
|
||||
|
||||
u32 a = AsUInt32();
|
||||
u32 b = addend.AsUInt32();
|
||||
u32 a = raw;
|
||||
u32 b = addend.raw;
|
||||
|
||||
//exponent difference
|
||||
s32 exp_diff = ((a >> 23) & 0xFF) - ((b >> 23) & 0xFF);
|
||||
|
@ -169,8 +156,8 @@ PS2Float PS2Float::Sub(PS2Float subtrahend)
|
|||
if (IsAbnormal() && subtrahend.IsAbnormal())
|
||||
return SolveAbnormalAdditionOrSubtractionOperation(*this, subtrahend, false);
|
||||
|
||||
u32 a = AsUInt32();
|
||||
u32 b = subtrahend.AsUInt32();
|
||||
u32 a = raw;
|
||||
u32 b = subtrahend.raw;
|
||||
|
||||
//exponent difference
|
||||
s32 exp_diff = ((a >> 23) & 0xFF) - ((b >> 23) & 0xFF);
|
||||
|
@ -203,7 +190,7 @@ PS2Float PS2Float::Sub(PS2Float subtrahend)
|
|||
}
|
||||
|
||||
|
||||
return PS2Float(a).DoAdd(Neg(PS2Float(b)));
|
||||
return PS2Float(a).DoAdd(PS2Float(b).Negate());
|
||||
}
|
||||
|
||||
PS2Float PS2Float::Mul(PS2Float mulend)
|
||||
|
@ -215,12 +202,7 @@ PS2Float PS2Float::Mul(PS2Float mulend)
|
|||
return SolveAbnormalMultiplicationOrDivisionOperation(*this, mulend, true);
|
||||
|
||||
if (IsZero() || mulend.IsZero())
|
||||
{
|
||||
PS2Float result = PS2Float(0);
|
||||
|
||||
result.Sign = DetermineMultiplicationDivisionOperationSign(*this, mulend);
|
||||
return result;
|
||||
}
|
||||
return PS2Float(DetermineMultiplicationDivisionOperationSign(*this, mulend), 0, 0);
|
||||
|
||||
return DoMul(mulend);
|
||||
}
|
||||
|
@ -234,12 +216,7 @@ PS2Float PS2Float::Div(PS2Float divend)
|
|||
return SolveAbnormalMultiplicationOrDivisionOperation(*this, divend, false);
|
||||
|
||||
if (IsZero())
|
||||
{
|
||||
PS2Float result = PS2Float(0);
|
||||
|
||||
result.Sign = DetermineMultiplicationDivisionOperationSign(*this, divend);
|
||||
return result;
|
||||
}
|
||||
return PS2Float(DetermineMultiplicationDivisionOperationSign(*this, divend), 0, 0);
|
||||
else if (divend.IsZero())
|
||||
return DetermineMultiplicationDivisionOperationSign(*this, divend) ? Min() : Max();
|
||||
|
||||
|
@ -258,7 +235,7 @@ PS2Float PS2Float::Sqrt()
|
|||
return PS2Float(0);
|
||||
|
||||
// PS2 only takes positive numbers for SQRT, and convert if necessary.
|
||||
s32 ix = (s32)(PS2Float(false, Exponent, Mantissa).AsUInt32());
|
||||
s32 ix = (s32)PS2Float(false, Exponent(), Mantissa()).raw;
|
||||
|
||||
/* extract mantissa and unbias exponent */
|
||||
s32 m = (ix >> 23) - BIAS;
|
||||
|
@ -308,39 +285,44 @@ PS2Float PS2Float::Rsqrt(PS2Float other)
|
|||
|
||||
bool PS2Float::IsDenormalized()
|
||||
{
|
||||
return Exponent == 0;
|
||||
return Exponent() == 0;
|
||||
}
|
||||
|
||||
bool PS2Float::IsAbnormal()
|
||||
{
|
||||
u32 val = AsUInt32();
|
||||
u32 val = raw;
|
||||
return val == MAX_FLOATING_POINT_VALUE || val == MIN_FLOATING_POINT_VALUE ||
|
||||
val == POSITIVE_INFINITY_VALUE || val == NEGATIVE_INFINITY_VALUE;
|
||||
}
|
||||
|
||||
bool PS2Float::IsZero()
|
||||
{
|
||||
return (Abs()) == 0;
|
||||
return Abs() == 0;
|
||||
}
|
||||
|
||||
u32 PS2Float::Abs()
|
||||
{
|
||||
return (AsUInt32() & MAX_FLOATING_POINT_VALUE);
|
||||
return (raw & MAX_FLOATING_POINT_VALUE);
|
||||
}
|
||||
|
||||
PS2Float PS2Float::Negate()
|
||||
{
|
||||
return PS2Float(raw ^ 0x80000000);
|
||||
}
|
||||
|
||||
PS2Float PS2Float::RoundTowardsZero()
|
||||
{
|
||||
return PS2Float((u32)(std::trunc((double)(AsUInt32()))));
|
||||
return PS2Float((u32)std::trunc((double)raw));
|
||||
}
|
||||
|
||||
s32 PS2Float::CompareTo(PS2Float other)
|
||||
{
|
||||
s32 selfTwoComplementVal = (s32)(Abs());
|
||||
if (Sign)
|
||||
s32 selfTwoComplementVal = (s32)Abs();
|
||||
if (Sign())
|
||||
selfTwoComplementVal = -selfTwoComplementVal;
|
||||
|
||||
s32 otherTwoComplementVal = (s32)(other.Abs());
|
||||
if (other.Sign)
|
||||
s32 otherTwoComplementVal = (s32)other.Abs();
|
||||
if (other.Sign())
|
||||
otherTwoComplementVal = -otherTwoComplementVal;
|
||||
|
||||
if (selfTwoComplementVal < otherTwoComplementVal)
|
||||
|
@ -353,8 +335,8 @@ s32 PS2Float::CompareTo(PS2Float other)
|
|||
|
||||
s32 PS2Float::CompareOperand(PS2Float other)
|
||||
{
|
||||
s32 selfTwoComplementVal = (s32)(Abs());
|
||||
s32 otherTwoComplementVal = (s32)(other.Abs());
|
||||
s32 selfTwoComplementVal = (s32)Abs();
|
||||
s32 otherTwoComplementVal = (s32)other.Abs();
|
||||
|
||||
if (selfTwoComplementVal < otherTwoComplementVal)
|
||||
return -1;
|
||||
|
@ -366,14 +348,14 @@ s32 PS2Float::CompareOperand(PS2Float other)
|
|||
|
||||
double PS2Float::ToDouble()
|
||||
{
|
||||
return std::bit_cast<double>(((u64)Sign << 63) | ((((u64)Exponent - BIAS) + 1023ULL) << 52) | ((u64)Mantissa << 29));
|
||||
return std::bit_cast<double>(((u64)Sign() << 63) | ((((u64)Exponent() - BIAS) + 1023ULL) << 52) | ((u64)Mantissa() << 29));
|
||||
}
|
||||
|
||||
std::string PS2Float::ToString()
|
||||
{
|
||||
double res = ToDouble();
|
||||
|
||||
u32 value = AsUInt32();
|
||||
u32 value = raw;
|
||||
std::ostringstream oss;
|
||||
oss << std::fixed << std::setprecision(6);
|
||||
|
||||
|
@ -409,8 +391,8 @@ PS2Float PS2Float::DoAdd(PS2Float other)
|
|||
{
|
||||
const u8 roundingMultiplier = 6;
|
||||
|
||||
u8 selfExponent = Exponent;
|
||||
s32 resExponent = selfExponent - other.Exponent;
|
||||
u8 selfExponent = Exponent();
|
||||
s32 resExponent = selfExponent - other.Exponent();
|
||||
|
||||
if (resExponent < 0)
|
||||
return other.DoAdd(*this);
|
||||
|
@ -418,10 +400,10 @@ PS2Float PS2Float::DoAdd(PS2Float other)
|
|||
return *this;
|
||||
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#ConditionalNegate
|
||||
u32 sign1 = (u32)((s32)AsUInt32() >> 31);
|
||||
s32 selfMantissa = (s32)(((Mantissa | 0x800000) ^ sign1) - sign1);
|
||||
u32 sign2 = (u32)((s32)other.AsUInt32() >> 31);
|
||||
s32 otherMantissa = (s32)(((other.Mantissa | 0x800000) ^ sign2) - sign2);
|
||||
u32 sign1 = (u32)((s32)raw >> 31);
|
||||
s32 selfMantissa = (s32)(((Mantissa() | 0x800000) ^ sign1) - sign1);
|
||||
u32 sign2 = (u32)((s32)other.raw >> 31);
|
||||
s32 otherMantissa = (s32)(((other.Mantissa() | 0x800000) ^ sign2) - sign2);
|
||||
|
||||
// PS2 multiply by 2 before doing the Math here.
|
||||
s32 man = (selfMantissa << roundingMultiplier) + ((otherMantissa << roundingMultiplier) >> resExponent);
|
||||
|
@ -450,11 +432,11 @@ PS2Float PS2Float::DoAdd(PS2Float other)
|
|||
|
||||
PS2Float PS2Float::DoMul(PS2Float other)
|
||||
{
|
||||
u8 selfExponent = Exponent;
|
||||
u8 otherExponent = other.Exponent;
|
||||
u32 selfMantissa = Mantissa | 0x800000;
|
||||
u32 otherMantissa = other.Mantissa | 0x800000;
|
||||
u32 sign = (AsUInt32() ^ other.AsUInt32()) & SIGNMASK;
|
||||
u8 selfExponent = Exponent();
|
||||
u8 otherExponent = other.Exponent();
|
||||
u32 selfMantissa = Mantissa() | 0x800000;
|
||||
u32 otherMantissa = other.Mantissa() | 0x800000;
|
||||
u32 sign = (raw ^ other.raw) & SIGNMASK;
|
||||
|
||||
s32 resExponent = selfExponent + otherExponent - 127;
|
||||
u32 resMantissa = (u32)(MulMantissa(selfMantissa, otherMantissa) >> 23);
|
||||
|
@ -476,25 +458,22 @@ PS2Float PS2Float::DoMul(PS2Float other)
|
|||
// Rounding can be slightly off: (PS2: 0x3F800000 / 0x3F800001 = 0x3F7FFFFF | SoftFloat/IEEE754: 0x3F800000 / 0x3F800001 = 0x3F7FFFFE).
|
||||
PS2Float PS2Float::DoDiv(PS2Float other)
|
||||
{
|
||||
bool sign = DetermineMultiplicationDivisionOperationSign(*this, other);
|
||||
u32 selfMantissa = Mantissa() | 0x800000;
|
||||
u32 otherMantissa = other.Mantissa() | 0x800000;
|
||||
s32 resExponent = Exponent() - other.Exponent() + BIAS;
|
||||
u64 selfMantissa64;
|
||||
u32 selfMantissa = Mantissa | 0x800000;
|
||||
u32 otherMantissa = other.Mantissa | 0x800000;
|
||||
s32 resExponent = Exponent - other.Exponent + BIAS;
|
||||
|
||||
PS2Float result = PS2Float(0);
|
||||
|
||||
result.Sign = DetermineMultiplicationDivisionOperationSign(*this, other);
|
||||
|
||||
if (resExponent > 255)
|
||||
return result.Sign ? Min() : Max();
|
||||
return sign ? Min() : Max();
|
||||
else if (resExponent <= 0)
|
||||
return PS2Float(result.Sign, 0, 0);
|
||||
return PS2Float(sign, 0, 0);
|
||||
|
||||
if (selfMantissa < otherMantissa)
|
||||
{
|
||||
--resExponent;
|
||||
if (resExponent == 0)
|
||||
return PS2Float(result.Sign, 0, 0);
|
||||
return PS2Float(sign, 0, 0);
|
||||
selfMantissa64 = (u64)(selfMantissa) << 31;
|
||||
}
|
||||
else
|
||||
|
@ -503,55 +482,55 @@ PS2Float PS2Float::DoDiv(PS2Float other)
|
|||
}
|
||||
|
||||
u32 resMantissa = (u32)(selfMantissa64 / otherMantissa);
|
||||
|
||||
if ((resMantissa & 0x3F) == 0)
|
||||
resMantissa |= ((u64)(otherMantissa)*resMantissa != selfMantissa64) ? 1U : 0;
|
||||
|
||||
result.Exponent = (u8)(resExponent);
|
||||
result.Mantissa = (resMantissa + 0x40U) >> 7;
|
||||
resMantissa = (resMantissa + 0x40U) >> 7;
|
||||
|
||||
if (result.Mantissa > 0)
|
||||
if (resMantissa > 0)
|
||||
{
|
||||
s32 leadingBitPosition = PS2Float::GetMostSignificantBitPosition(result.Mantissa);
|
||||
s32 leadingBitPosition = PS2Float::GetMostSignificantBitPosition(resMantissa);
|
||||
|
||||
while (leadingBitPosition != IMPLICIT_LEADING_BIT_POS)
|
||||
{
|
||||
if (leadingBitPosition > IMPLICIT_LEADING_BIT_POS)
|
||||
{
|
||||
result.Mantissa >>= 1;
|
||||
resMantissa >>= 1;
|
||||
|
||||
s32 exp = ((s32)result.Exponent + 1);
|
||||
s32 exp = resExponent + 1;
|
||||
|
||||
if (exp > 255)
|
||||
return result.Sign ? Min() : Max();
|
||||
return sign ? Min() : Max();
|
||||
|
||||
result.Exponent = (u8)exp;
|
||||
resExponent = exp;
|
||||
|
||||
leadingBitPosition--;
|
||||
}
|
||||
else if (leadingBitPosition < IMPLICIT_LEADING_BIT_POS)
|
||||
{
|
||||
result.Mantissa <<= 1;
|
||||
resMantissa <<= 1;
|
||||
|
||||
s32 exp = ((s32)result.Exponent - 1);
|
||||
s32 exp = resExponent - 1;
|
||||
|
||||
if (exp <= 0)
|
||||
return PS2Float(result.Sign, 0, 0);
|
||||
return PS2Float(sign, 0, 0);
|
||||
|
||||
result.Exponent = (u8)exp;
|
||||
resExponent = exp;
|
||||
|
||||
leadingBitPosition++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.Mantissa &= 0x7FFFFF;
|
||||
return result.RoundTowardsZero();
|
||||
resMantissa &= 0x7FFFFF;
|
||||
return PS2Float(sign, (u8)resExponent, resMantissa).RoundTowardsZero();
|
||||
}
|
||||
|
||||
PS2Float PS2Float::SolveAbnormalAdditionOrSubtractionOperation(PS2Float a, PS2Float b, bool add)
|
||||
{
|
||||
u32 aval = a.AsUInt32();
|
||||
u32 bval = b.AsUInt32();
|
||||
u32 aval = a.raw;
|
||||
u32 bval = b.raw;
|
||||
|
||||
if (aval == MAX_FLOATING_POINT_VALUE && bval == MAX_FLOATING_POINT_VALUE)
|
||||
return add ? Max() : PS2Float(0);
|
||||
|
@ -608,8 +587,8 @@ PS2Float PS2Float::SolveAbnormalAdditionOrSubtractionOperation(PS2Float a, PS2Fl
|
|||
|
||||
PS2Float PS2Float::SolveAbnormalMultiplicationOrDivisionOperation(PS2Float a, PS2Float b, bool mul)
|
||||
{
|
||||
u32 aval = a.AsUInt32();
|
||||
u32 bval = b.AsUInt32();
|
||||
u32 aval = a.raw;
|
||||
u32 bval = b.raw;
|
||||
|
||||
if (mul)
|
||||
{
|
||||
|
@ -711,38 +690,31 @@ PS2Float PS2Float::SolveAbnormalMultiplicationOrDivisionOperation(PS2Float a, PS
|
|||
|
||||
PS2Float PS2Float::SolveAddSubDenormalizedOperation(PS2Float a, PS2Float b, bool add)
|
||||
{
|
||||
PS2Float result = PS2Float(0);
|
||||
bool sign = add ? DetermineAdditionOperationSign(a, b) : DetermineSubtractionOperationSign(a, b);
|
||||
|
||||
if (a.IsDenormalized() && !b.IsDenormalized())
|
||||
result = b;
|
||||
return PS2Float(sign, b.Exponent(), b.Mantissa());
|
||||
else if (!a.IsDenormalized() && b.IsDenormalized())
|
||||
result = a;
|
||||
return PS2Float(sign, a.Exponent(), a.Mantissa());
|
||||
else if (a.IsDenormalized() && b.IsDenormalized())
|
||||
{
|
||||
}
|
||||
return PS2Float(sign, 0, 0);
|
||||
else
|
||||
Console.Error("Both numbers are not denormalized");
|
||||
|
||||
result.Sign = add ? DetermineAdditionOperationSign(a, b) : DetermineSubtractionOperationSign(a, b);
|
||||
return result;
|
||||
return PS2Float(0);
|
||||
}
|
||||
|
||||
PS2Float PS2Float::SolveMultiplicationDenormalizedOperation(PS2Float a, PS2Float b)
|
||||
{
|
||||
PS2Float result = PS2Float(0);
|
||||
|
||||
result.Sign = DetermineMultiplicationDivisionOperationSign(a, b);
|
||||
return result;
|
||||
return PS2Float(DetermineMultiplicationDivisionOperationSign(a, b), 0, 0);
|
||||
}
|
||||
|
||||
PS2Float PS2Float::SolveDivisionDenormalizedOperation(PS2Float a, PS2Float b)
|
||||
{
|
||||
bool sign = DetermineMultiplicationDivisionOperationSign(a, b);
|
||||
PS2Float result = PS2Float(0);
|
||||
|
||||
if (a.IsDenormalized() && !b.IsDenormalized())
|
||||
{
|
||||
}
|
||||
return PS2Float(sign, 0, 0);
|
||||
else if (!a.IsDenormalized() && b.IsDenormalized())
|
||||
return sign ? Min() : Max();
|
||||
else if (a.IsDenormalized() && b.IsDenormalized())
|
||||
|
@ -750,48 +722,42 @@ PS2Float PS2Float::SolveDivisionDenormalizedOperation(PS2Float a, PS2Float b)
|
|||
else
|
||||
Console.Error("Both numbers are not denormalized");
|
||||
|
||||
result.Sign = sign;
|
||||
return result;
|
||||
}
|
||||
|
||||
PS2Float PS2Float::Neg(PS2Float self)
|
||||
{
|
||||
return PS2Float(self.AsUInt32() ^ SIGNMASK);
|
||||
return PS2Float(0);
|
||||
}
|
||||
|
||||
bool PS2Float::DetermineMultiplicationDivisionOperationSign(PS2Float a, PS2Float b)
|
||||
{
|
||||
return a.Sign ^ b.Sign;
|
||||
return a.Sign() ^ b.Sign();
|
||||
}
|
||||
|
||||
bool PS2Float::DetermineAdditionOperationSign(PS2Float a, PS2Float b)
|
||||
{
|
||||
if (a.IsZero() && b.IsZero())
|
||||
{
|
||||
if (!a.Sign || !b.Sign)
|
||||
if (!a.Sign() || !b.Sign())
|
||||
return false;
|
||||
else if (a.Sign && b.Sign)
|
||||
else if (a.Sign() && b.Sign())
|
||||
return true;
|
||||
else
|
||||
Console.Error("Unhandled addition operation flags");
|
||||
}
|
||||
|
||||
return a.CompareOperand(b) >= 0 ? a.Sign : b.Sign;
|
||||
return a.CompareOperand(b) >= 0 ? a.Sign() : b.Sign();
|
||||
}
|
||||
|
||||
bool PS2Float::DetermineSubtractionOperationSign(PS2Float a, PS2Float b)
|
||||
{
|
||||
if (a.IsZero() && b.IsZero())
|
||||
{
|
||||
if (!a.Sign || b.Sign)
|
||||
if (!a.Sign() || b.Sign())
|
||||
return false;
|
||||
else if (a.Sign && !b.Sign)
|
||||
else if (a.Sign() && !b.Sign())
|
||||
return true;
|
||||
else
|
||||
Console.Error("Unhandled subtraction operation flags");
|
||||
}
|
||||
|
||||
return a.CompareOperand(b) >= 0 ? a.Sign : !b.Sign;
|
||||
return a.CompareOperand(b) >= 0 ? a.Sign() : !b.Sign();
|
||||
}
|
||||
|
||||
s32 PS2Float::clz(s32 x)
|
||||
|
|
|
@ -26,10 +26,7 @@ class PS2Float
|
|||
static AddResult Add3(u32 a, u32 b, u32 c);
|
||||
|
||||
public:
|
||||
bool Sign;
|
||||
u8 Exponent;
|
||||
u32 Mantissa;
|
||||
|
||||
|
||||
static constexpr u8 BIAS = 127;
|
||||
static constexpr u32 SIGNMASK = 0x80000000;
|
||||
static constexpr u32 MAX_FLOATING_POINT_VALUE = 0x7FFFFFFF;
|
||||
|
@ -62,6 +59,12 @@ public:
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 24, 24, 24, 24, 24, 24, 24
|
||||
};
|
||||
|
||||
u32 raw;
|
||||
|
||||
constexpr u32 Mantissa() const { return raw & 0x7FFFFF; }
|
||||
constexpr u8 Exponent() const { return (raw >> 23) & 0xFF; }
|
||||
constexpr bool Sign() const { return ((raw >> 31) & 1) != 0; }
|
||||
|
||||
PS2Float(u32 value);
|
||||
|
||||
PS2Float(bool sign, u8 exponent, u32 mantissa);
|
||||
|
@ -74,10 +77,6 @@ public:
|
|||
|
||||
static PS2Float MinOne();
|
||||
|
||||
static PS2Float Neg(PS2Float self);
|
||||
|
||||
u32 AsUInt32() const;
|
||||
|
||||
PS2Float Add(PS2Float addend);
|
||||
|
||||
PS2Float Sub(PS2Float subtrahend);
|
||||
|
@ -98,6 +97,8 @@ public:
|
|||
|
||||
u32 Abs();
|
||||
|
||||
PS2Float Negate();
|
||||
|
||||
PS2Float RoundTowardsZero();
|
||||
|
||||
s32 CompareTo(PS2Float other);
|
||||
|
|
|
@ -16,8 +16,8 @@ static __ri u32 VU_MAC_UPDATE(int shift, VURegs* VU, u32 f)
|
|||
{
|
||||
PS2Float ps2f = PS2Float(f);
|
||||
|
||||
u32 exp = ps2f.Exponent;
|
||||
u32 s = ps2f.AsUInt32() & PS2Float::SIGNMASK;
|
||||
u32 exp = ps2f.Exponent();
|
||||
u32 s = ps2f.raw & PS2Float::SIGNMASK;
|
||||
|
||||
if (s)
|
||||
VU->macflag |= 0x0010<<shift;
|
||||
|
|
|
@ -465,28 +465,28 @@ static __fi float vuDouble(u32 f)
|
|||
|
||||
static __fi u32 vuAccurateAdd(VURegs* VU, u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_VU_SOFT_ADDSUB((VU == &VU1) ? 1 : 0)) return PS2Float(a).Add(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_VU_SOFT_ADDSUB((VU == &VU1) ? 1 : 0)) return PS2Float(a).Add(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(vuDouble(a) + vuDouble(b));
|
||||
}
|
||||
|
||||
static __fi u32 vuAccurateSub(VURegs* VU, u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_VU_SOFT_ADDSUB((VU == &VU1) ? 1 : 0)) return PS2Float(a).Sub(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_VU_SOFT_ADDSUB((VU == &VU1) ? 1 : 0)) return PS2Float(a).Sub(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(vuDouble(a) - vuDouble(b));
|
||||
}
|
||||
|
||||
static __fi u32 vuAccurateMul(VURegs* VU, u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0)) return PS2Float(a).Mul(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0)) return PS2Float(a).Mul(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(vuDouble(a) * vuDouble(b));
|
||||
}
|
||||
|
||||
static __fi u32 vuAccurateDiv(VURegs* VU, u32 a, u32 b)
|
||||
{
|
||||
if (CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0)) return PS2Float(a).Div(PS2Float(b)).AsUInt32();
|
||||
if (CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0)) return PS2Float(a).Div(PS2Float(b)).raw;
|
||||
|
||||
return std::bit_cast<u32>(vuDouble(a) / vuDouble(b));
|
||||
}
|
||||
|
@ -1778,7 +1778,7 @@ static __fi void _vuDIV(VURegs* VU)
|
|||
}
|
||||
else
|
||||
{
|
||||
VU->q.UL = fs.Div(ft).AsUInt32();
|
||||
VU->q.UL = fs.Div(ft).raw;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1819,7 +1819,7 @@ static __fi void _vuSQRT(VURegs* VU)
|
|||
|
||||
if (ft.ToDouble() < 0.0)
|
||||
VU->statusflag |= 0x10;
|
||||
VU->q.UL = PS2Float(ft.Abs()).Sqrt().AsUInt32();
|
||||
VU->q.UL = PS2Float(ft.Abs()).Sqrt().raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1874,11 +1874,11 @@ static __fi void _vuRSQRT(VURegs* VU)
|
|||
}
|
||||
|
||||
if (CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0))
|
||||
VU->q.UL = fs.Div(PS2Float(ft.Abs()).Sqrt()).AsUInt32();
|
||||
VU->q.UL = fs.Div(PS2Float(ft.Abs()).Sqrt()).raw;
|
||||
else
|
||||
{
|
||||
float temp = sqrt(fabs(vuDouble(ft.AsUInt32())));
|
||||
VU->q.F = vuDouble(fs.AsUInt32()) / temp;
|
||||
float temp = sqrt(fabs(vuDouble(ft.raw)));
|
||||
VU->q.F = vuDouble(fs.raw) / temp;
|
||||
VU->q.F = vuDouble(VU->q.UL);
|
||||
}
|
||||
}
|
||||
|
@ -2589,12 +2589,12 @@ static __ri void _vuERSADD(VURegs* VU)
|
|||
p = PS2Float::One().Div(p);
|
||||
else
|
||||
{
|
||||
VU->p.F = 1.0f / vuDouble(p.AsUInt32());
|
||||
VU->p.F = 1.0f / vuDouble(p.raw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VU->p.UL = p.AsUInt32();
|
||||
VU->p.UL = p.raw;
|
||||
}
|
||||
|
||||
static __ri void _vuELENG(VURegs* VU)
|
||||
|
@ -2611,11 +2611,11 @@ static __ri void _vuELENG(VURegs* VU)
|
|||
{
|
||||
value = value.Sqrt();
|
||||
}
|
||||
VU->p.UL = value.AsUInt32();
|
||||
VU->p.UL = value.raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
float p = vuDouble(value.AsUInt32());
|
||||
float p = vuDouble(value.raw);
|
||||
|
||||
if (p >= 0)
|
||||
{
|
||||
|
@ -2646,16 +2646,16 @@ static __ri void _vuERLENG(VURegs* VU)
|
|||
}
|
||||
else
|
||||
{
|
||||
VU->p.F = 1.0 / vuDouble(value.AsUInt32());
|
||||
VU->p.F = 1.0 / vuDouble(value.raw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
VU->p.UL = value.AsUInt32();
|
||||
VU->p.UL = value.raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
float p = vuDouble(value.AsUInt32());
|
||||
float p = vuDouble(value.raw);
|
||||
|
||||
if (p >= 0)
|
||||
{
|
||||
|
@ -2731,12 +2731,12 @@ static __ri void _vuERCPR(VURegs* VU)
|
|||
}
|
||||
else
|
||||
{
|
||||
VU->p.F = 1.0 / vuDouble(p.AsUInt32());
|
||||
VU->p.F = 1.0 / vuDouble(p.raw);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
VU->p.UL = p.AsUInt32();
|
||||
VU->p.UL = p.raw;
|
||||
}
|
||||
|
||||
static __ri void _vuESQRT(VURegs* VU)
|
||||
|
@ -2750,7 +2750,7 @@ static __ri void _vuESQRT(VURegs* VU)
|
|||
value = value.Sqrt();
|
||||
}
|
||||
|
||||
VU->p.UL = value.AsUInt32();
|
||||
VU->p.UL = value.raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2778,7 +2778,7 @@ static __ri void _vuERSQRT(VURegs* VU)
|
|||
{
|
||||
if (CHECK_VU_SOFT_MULDIV((VU == &VU1) ? 1 : 0))
|
||||
{
|
||||
VU->p.F = 1.0f / vuDouble(value.AsUInt32());
|
||||
VU->p.F = 1.0f / vuDouble(value.raw);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -2788,7 +2788,7 @@ static __ri void _vuERSQRT(VURegs* VU)
|
|||
}
|
||||
}
|
||||
|
||||
VU->p.UL = value.AsUInt32();
|
||||
VU->p.UL = value.raw;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue