mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-02-25 10:11:08 +00:00
128 lines
3.8 KiB
C#
128 lines
3.8 KiB
C#
using ARMeilleure.State;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace ARMeilleure.Instructions
|
|
{
|
|
static class SoftFloat64_16
|
|
{
|
|
[UnmanagedCallersOnly]
|
|
public static ushort FPConvert(double value)
|
|
{
|
|
ExecutionContext context = NativeInterface.GetContext();
|
|
|
|
double real = value.FPUnpackCv(out FPType type, out bool sign, out ulong valueBits, context);
|
|
|
|
bool altHp = (context.Fpcr & FPCR.Ahp) != 0;
|
|
|
|
ushort resultBits;
|
|
|
|
if (type is FPType.SNaN or FPType.QNaN)
|
|
{
|
|
if (altHp)
|
|
{
|
|
resultBits = SoftFloat16.FPZero(sign);
|
|
}
|
|
else if ((context.Fpcr & FPCR.Dn) != 0)
|
|
{
|
|
resultBits = SoftFloat16.FPDefaultNaN();
|
|
}
|
|
else
|
|
{
|
|
resultBits = FPConvertNaN(valueBits);
|
|
}
|
|
|
|
if (type == FPType.SNaN || altHp)
|
|
{
|
|
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
|
}
|
|
}
|
|
else if (type == FPType.Infinity)
|
|
{
|
|
if (altHp)
|
|
{
|
|
resultBits = (ushort)((sign ? 1u : 0u) << 15 | 0x7FFFu);
|
|
|
|
SoftFloat.FPProcessException(FPException.InvalidOp, context);
|
|
}
|
|
else
|
|
{
|
|
resultBits = SoftFloat16.FPInfinity(sign);
|
|
}
|
|
}
|
|
else if (type == FPType.Zero)
|
|
{
|
|
resultBits = SoftFloat16.FPZero(sign);
|
|
}
|
|
else
|
|
{
|
|
resultBits = SoftFloat16.FPRoundCv(real, context);
|
|
}
|
|
|
|
return resultBits;
|
|
}
|
|
|
|
private static double FPUnpackCv(
|
|
this double value,
|
|
out FPType type,
|
|
out bool sign,
|
|
out ulong valueBits,
|
|
ExecutionContext context)
|
|
{
|
|
valueBits = (ulong)BitConverter.DoubleToInt64Bits(value);
|
|
|
|
sign = (~valueBits & 0x8000000000000000ul) == 0u;
|
|
|
|
ulong exp64 = (valueBits & 0x7FF0000000000000ul) >> 52;
|
|
ulong frac64 = valueBits & 0x000FFFFFFFFFFFFFul;
|
|
|
|
double real;
|
|
|
|
if (exp64 == 0u)
|
|
{
|
|
if (frac64 == 0u || (context.Fpcr & FPCR.Fz) != 0)
|
|
{
|
|
type = FPType.Zero;
|
|
real = 0d;
|
|
|
|
if (frac64 != 0u)
|
|
{
|
|
SoftFloat.FPProcessException(FPException.InputDenorm, context);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
type = FPType.Nonzero; // Subnormal.
|
|
real = Math.Pow(2d, -1022) * ((double)frac64 * Math.Pow(2d, -52));
|
|
}
|
|
}
|
|
else if (exp64 == 0x7FFul)
|
|
{
|
|
if (frac64 == 0u)
|
|
{
|
|
type = FPType.Infinity;
|
|
real = Math.Pow(2d, 1000000);
|
|
}
|
|
else
|
|
{
|
|
type = (~frac64 & 0x0008000000000000ul) == 0u ? FPType.QNaN : FPType.SNaN;
|
|
real = 0d;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
type = FPType.Nonzero; // Normal.
|
|
real = Math.Pow(2d, (int)exp64 - 1023) * (1d + (double)frac64 * Math.Pow(2d, -52));
|
|
}
|
|
|
|
return sign ? -real : real;
|
|
}
|
|
|
|
private static ushort FPConvertNaN(ulong valueBits)
|
|
{
|
|
return (ushort)((valueBits & 0x8000000000000000ul) >> 48 | 0x7E00u |
|
|
(valueBits & 0x0007FC0000000000ul) >> 42);
|
|
}
|
|
}
|
|
}
|