Update ASoftFloat.cs
This commit is contained in:
parent
b9b89bad2f
commit
66a2cf186b
1 changed files with 221 additions and 78 deletions
|
@ -1,5 +1,4 @@
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
@ -271,11 +270,6 @@ namespace ChocolArm64.Instruction
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = Value1 + Value2;
|
Result = Value1 + Value2;
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,13 +530,10 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T);
|
||||||
// https://github.com/dotnet/corefx/issues/31903
|
// https://github.com/dotnet/corefx/issues/31903
|
||||||
Result = ValueA + (Value1 * Value2);
|
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
Result = ValueA + (Value1 * Value2);
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,13 +576,10 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T);
|
||||||
// https://github.com/dotnet/corefx/issues/31903
|
// https://github.com/dotnet/corefx/issues/31903
|
||||||
Result = 2f + (Value1 * Value2);
|
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
Result = 2f + (Value1 * Value2);
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,19 +612,50 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: When available, use: T MathF.FusedMultiplyAdd(T, T, T);
|
||||||
// https://github.com/dotnet/corefx/issues/31903
|
// https://github.com/dotnet/corefx/issues/31903
|
||||||
Result = (3f + (Value1 * Value2)) / 2f;
|
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
Result = (3f + (Value1 * Value2)) / 2f;
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static float FPSqrt(float Value, AThreadState State)
|
||||||
|
{
|
||||||
|
Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSqrt: State.Fpcr = 0x{State.Fpcr:X8}");
|
||||||
|
|
||||||
|
Value = Value.FPUnpack(out FPType Type, out bool Sign, out uint Op);
|
||||||
|
|
||||||
|
float Result;
|
||||||
|
|
||||||
|
if (Type == FPType.SNaN || Type == FPType.QNaN)
|
||||||
|
{
|
||||||
|
Result = FPProcessNaN(Type, Op, State);
|
||||||
|
}
|
||||||
|
else if (Type == FPType.Zero)
|
||||||
|
{
|
||||||
|
Result = FPZero(Sign);
|
||||||
|
}
|
||||||
|
else if (Type == FPType.Infinity && !Sign)
|
||||||
|
{
|
||||||
|
Result = FPInfinity(Sign);
|
||||||
|
}
|
||||||
|
else if (Sign)
|
||||||
|
{
|
||||||
|
Result = FPDefaultNaN();
|
||||||
|
|
||||||
|
FPProcessException(FPExc.InvalidOp, State);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = MathF.Sqrt(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
public static float FPSub(float Value1, float Value2, AThreadState State)
|
public static float FPSub(float Value1, float Value2, AThreadState State)
|
||||||
{
|
{
|
||||||
Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
|
Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_32.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
|
||||||
|
@ -672,28 +691,74 @@ namespace ChocolArm64.Instruction
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = Value1 - Value2;
|
Result = Value1 - Value2;
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum FPType { Nonzero, Zero, Infinity, QNaN, SNaN };
|
private enum FPType
|
||||||
private enum FPExc { InvalidOp, DivideByZero, Overflow, Underflow, Inexact, InputDenorm = 7 };
|
{
|
||||||
private enum FPRounding { TIEEVEN, POSINF, NEGINF, ZERO };
|
Nonzero,
|
||||||
|
Zero,
|
||||||
|
Infinity,
|
||||||
|
QNaN,
|
||||||
|
SNaN
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static float FPDefaultNaN() => -float.NaN;
|
private enum FPExc
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static float FPInfinity(bool Sign) => Sign ? float.NegativeInfinity : float.PositiveInfinity;
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static float FPZero(bool Sign) => Sign ? -0f : +0f;
|
InvalidOp,
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static float FPTwo(bool Sign) => Sign ? -2f : +2f;
|
DivideByZero,
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static float FPOnePointFive(bool Sign) => Sign ? -1.5f : +1.5f;
|
Overflow,
|
||||||
|
Underflow,
|
||||||
|
Inexact,
|
||||||
|
InputDenorm = 7
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static float FPNeg(this float Value) => -Value;
|
private enum FPRounding
|
||||||
|
{
|
||||||
|
TIEEVEN,
|
||||||
|
POSINF,
|
||||||
|
NEGINF,
|
||||||
|
ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static float FPDefaultNaN()
|
||||||
|
{
|
||||||
|
return -float.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static float FPInfinity(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? float.NegativeInfinity : float.PositiveInfinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static float FPZero(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? -0f : +0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static float FPTwo(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? -2f : +2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static float FPOnePointFive(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? -1.5f : +1.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static float FPNeg(this float Value)
|
||||||
|
{
|
||||||
|
return -Value;
|
||||||
|
}
|
||||||
|
|
||||||
private static float FPUnpack(this float Value, out FPType Type, out bool Sign, out uint ValueBits)
|
private static float FPUnpack(this float Value, out FPType Type, out bool Sign, out uint ValueBits)
|
||||||
{
|
{
|
||||||
|
@ -736,8 +801,10 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float FPProcessNaNs(
|
private static float FPProcessNaNs(
|
||||||
FPType Type1, FPType Type2,
|
FPType Type1,
|
||||||
uint Op1, uint Op2,
|
FPType Type2,
|
||||||
|
uint Op1,
|
||||||
|
uint Op2,
|
||||||
AThreadState State,
|
AThreadState State,
|
||||||
out bool Done)
|
out bool Done)
|
||||||
{
|
{
|
||||||
|
@ -766,8 +833,12 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float FPProcessNaNs3(
|
private static float FPProcessNaNs3(
|
||||||
FPType Type1, FPType Type2, FPType Type3,
|
FPType Type1,
|
||||||
uint Op1, uint Op2, uint Op3,
|
FPType Type2,
|
||||||
|
FPType Type3,
|
||||||
|
uint Op1,
|
||||||
|
uint Op2,
|
||||||
|
uint Op3,
|
||||||
AThreadState State,
|
AThreadState State,
|
||||||
out bool Done)
|
out bool Done)
|
||||||
{
|
{
|
||||||
|
@ -882,11 +953,6 @@ namespace ChocolArm64.Instruction
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = Value1 + Value2;
|
Result = Value1 + Value2;
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1147,13 +1213,10 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T);
|
||||||
// https://github.com/dotnet/corefx/issues/31903
|
// https://github.com/dotnet/corefx/issues/31903
|
||||||
Result = ValueA + (Value1 * Value2);
|
|
||||||
|
|
||||||
/*if (Result == 0d) // -Zero, +Zero
|
Result = ValueA + (Value1 * Value2);
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1196,13 +1259,10 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T);
|
||||||
// https://github.com/dotnet/corefx/issues/31903
|
// https://github.com/dotnet/corefx/issues/31903
|
||||||
Result = 2d + (Value1 * Value2);
|
|
||||||
|
|
||||||
/*if (Result == 0d) // -Zero, +Zero
|
Result = 2d + (Value1 * Value2);
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1235,19 +1295,50 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// TODO: When available, use: T Math.FusedMultiplyAdd(T, T, T);
|
||||||
// https://github.com/dotnet/corefx/issues/31903
|
// https://github.com/dotnet/corefx/issues/31903
|
||||||
Result = (3d + (Value1 * Value2)) / 2d;
|
|
||||||
|
|
||||||
/*if (Result == 0d) // -Zero, +Zero
|
Result = (3d + (Value1 * Value2)) / 2d;
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static double FPSqrt(double Value, AThreadState State)
|
||||||
|
{
|
||||||
|
Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSqrt: State.Fpcr = 0x{State.Fpcr:X8}");
|
||||||
|
|
||||||
|
Value = Value.FPUnpack(out FPType Type, out bool Sign, out ulong Op);
|
||||||
|
|
||||||
|
double Result;
|
||||||
|
|
||||||
|
if (Type == FPType.SNaN || Type == FPType.QNaN)
|
||||||
|
{
|
||||||
|
Result = FPProcessNaN(Type, Op, State);
|
||||||
|
}
|
||||||
|
else if (Type == FPType.Zero)
|
||||||
|
{
|
||||||
|
Result = FPZero(Sign);
|
||||||
|
}
|
||||||
|
else if (Type == FPType.Infinity && !Sign)
|
||||||
|
{
|
||||||
|
Result = FPInfinity(Sign);
|
||||||
|
}
|
||||||
|
else if (Sign)
|
||||||
|
{
|
||||||
|
Result = FPDefaultNaN();
|
||||||
|
|
||||||
|
FPProcessException(FPExc.InvalidOp, State);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = Math.Sqrt(Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
public static double FPSub(double Value1, double Value2, AThreadState State)
|
public static double FPSub(double Value1, double Value2, AThreadState State)
|
||||||
{
|
{
|
||||||
Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
|
Debug.WriteLineIf(State.Fpcr != 0, $"ASoftFloat_64.FPSub: State.Fpcr = 0x{State.Fpcr:X8}");
|
||||||
|
@ -1283,28 +1374,74 @@ namespace ChocolArm64.Instruction
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Result = Value1 - Value2;
|
Result = Value1 - Value2;
|
||||||
|
|
||||||
/*if (Result == 0f) // -Zero, +Zero
|
|
||||||
{
|
|
||||||
Result = FPZero(FPRoundingMode(State) == FPRounding.NEGINF);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private enum FPType { Nonzero, Zero, Infinity, QNaN, SNaN };
|
private enum FPType
|
||||||
private enum FPExc { InvalidOp, DivideByZero, Overflow, Underflow, Inexact, InputDenorm = 7 };
|
{
|
||||||
private enum FPRounding { TIEEVEN, POSINF, NEGINF, ZERO };
|
Nonzero,
|
||||||
|
Zero,
|
||||||
|
Infinity,
|
||||||
|
QNaN,
|
||||||
|
SNaN
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static double FPDefaultNaN() => -double.NaN;
|
private enum FPExc
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static double FPInfinity(bool Sign) => Sign ? double.NegativeInfinity : double.PositiveInfinity;
|
{
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static double FPZero(bool Sign) => Sign ? -0d : +0d;
|
InvalidOp,
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static double FPTwo(bool Sign) => Sign ? -2d : +2d;
|
DivideByZero,
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static double FPOnePointFive(bool Sign) => Sign ? -1.5d : +1.5d;
|
Overflow,
|
||||||
|
Underflow,
|
||||||
|
Inexact,
|
||||||
|
InputDenorm = 7
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)] private static double FPNeg(this double Value) => -Value;
|
private enum FPRounding
|
||||||
|
{
|
||||||
|
TIEEVEN,
|
||||||
|
POSINF,
|
||||||
|
NEGINF,
|
||||||
|
ZERO
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double FPDefaultNaN()
|
||||||
|
{
|
||||||
|
return -double.NaN;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double FPInfinity(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? double.NegativeInfinity : double.PositiveInfinity;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double FPZero(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? -0d : +0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double FPTwo(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? -2d : +2d;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double FPOnePointFive(bool Sign)
|
||||||
|
{
|
||||||
|
return Sign ? -1.5d : +1.5d;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
|
private static double FPNeg(this double Value)
|
||||||
|
{
|
||||||
|
return -Value;
|
||||||
|
}
|
||||||
|
|
||||||
private static double FPUnpack(this double Value, out FPType Type, out bool Sign, out ulong ValueBits)
|
private static double FPUnpack(this double Value, out FPType Type, out bool Sign, out ulong ValueBits)
|
||||||
{
|
{
|
||||||
|
@ -1331,7 +1468,7 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Type = (~ValueBits & 0x8000000000000ul) == 0ul
|
Type = (~ValueBits & 0x0008000000000000ul) == 0ul
|
||||||
? FPType.QNaN
|
? FPType.QNaN
|
||||||
: FPType.SNaN;
|
: FPType.SNaN;
|
||||||
|
|
||||||
|
@ -1347,8 +1484,10 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double FPProcessNaNs(
|
private static double FPProcessNaNs(
|
||||||
FPType Type1, FPType Type2,
|
FPType Type1,
|
||||||
ulong Op1, ulong Op2,
|
FPType Type2,
|
||||||
|
ulong Op1,
|
||||||
|
ulong Op2,
|
||||||
AThreadState State,
|
AThreadState State,
|
||||||
out bool Done)
|
out bool Done)
|
||||||
{
|
{
|
||||||
|
@ -1377,8 +1516,12 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double FPProcessNaNs3(
|
private static double FPProcessNaNs3(
|
||||||
FPType Type1, FPType Type2, FPType Type3,
|
FPType Type1,
|
||||||
ulong Op1, ulong Op2, ulong Op3,
|
FPType Type2,
|
||||||
|
FPType Type3,
|
||||||
|
ulong Op1,
|
||||||
|
ulong Op2,
|
||||||
|
ulong Op3,
|
||||||
AThreadState State,
|
AThreadState State,
|
||||||
out bool Done)
|
out bool Done)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue