Update SoftFallback.cs
This commit is contained in:
parent
0a2456628f
commit
586fced2a4
1 changed files with 278 additions and 1 deletions
|
@ -16,6 +16,283 @@ namespace ChocolArm64.Instructions
|
||||||
context.EmitCall(typeof(SoftFallback), mthdName);
|
context.EmitCall(typeof(SoftFallback), mthdName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region "ShlReg"
|
||||||
|
public static long SignedShlReg(long value, long shift, bool round, int size)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
int shiftLsB = (sbyte)shift;
|
||||||
|
|
||||||
|
if (shiftLsB < 0)
|
||||||
|
{
|
||||||
|
return SignedShrReg(value, -shiftLsB, round, eSize);
|
||||||
|
}
|
||||||
|
else if (shiftLsB > 0)
|
||||||
|
{
|
||||||
|
if (shiftLsB >= eSize)
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value << shiftLsB;
|
||||||
|
}
|
||||||
|
else /* if (shiftLsB == 0) */
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
int shiftLsB = (sbyte)shift;
|
||||||
|
|
||||||
|
if (shiftLsB < 0)
|
||||||
|
{
|
||||||
|
return UnsignedShrReg(value, -shiftLsB, round, eSize);
|
||||||
|
}
|
||||||
|
else if (shiftLsB > 0)
|
||||||
|
{
|
||||||
|
if (shiftLsB >= eSize)
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value << shiftLsB;
|
||||||
|
}
|
||||||
|
else /* if (shiftLsB == 0) */
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long SignedShlRegSatQ(long value, long shift, bool round, int size, CpuThreadState state)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
int shiftLsB = (sbyte)shift;
|
||||||
|
|
||||||
|
if (shiftLsB < 0)
|
||||||
|
{
|
||||||
|
return SignedShrReg(value, -shiftLsB, round, eSize);
|
||||||
|
}
|
||||||
|
else if (shiftLsB > 0)
|
||||||
|
{
|
||||||
|
if (shiftLsB >= eSize)
|
||||||
|
{
|
||||||
|
return SignedSignSatQ(value, eSize, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
long shl = value << shiftLsB;
|
||||||
|
long shr = shl >> shiftLsB;
|
||||||
|
|
||||||
|
if (shr != value)
|
||||||
|
{
|
||||||
|
return SignedSignSatQ(value, eSize, state);
|
||||||
|
}
|
||||||
|
else /* if (shr == value) */
|
||||||
|
{
|
||||||
|
return shl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (eSize != 64) */
|
||||||
|
{
|
||||||
|
return SignedSrcSignedDstSatQ(value << shiftLsB, size, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (shiftLsB == 0) */
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size, CpuThreadState state)
|
||||||
|
{
|
||||||
|
int eSize = 8 << size;
|
||||||
|
|
||||||
|
int shiftLsB = (sbyte)shift;
|
||||||
|
|
||||||
|
if (shiftLsB < 0)
|
||||||
|
{
|
||||||
|
return UnsignedShrReg(value, -shiftLsB, round, eSize);
|
||||||
|
}
|
||||||
|
else if (shiftLsB > 0)
|
||||||
|
{
|
||||||
|
if (shiftLsB >= eSize)
|
||||||
|
{
|
||||||
|
return UnsignedSignSatQ(value, eSize, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
ulong shl = value << shiftLsB;
|
||||||
|
ulong shr = shl >> shiftLsB;
|
||||||
|
|
||||||
|
if (shr != value)
|
||||||
|
{
|
||||||
|
return UnsignedSignSatQ(value, eSize, state);
|
||||||
|
}
|
||||||
|
else /* if (shr == value) */
|
||||||
|
{
|
||||||
|
return shl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (eSize != 64) */
|
||||||
|
{
|
||||||
|
return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (shiftLsB == 0) */
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
|
||||||
|
{
|
||||||
|
if (round)
|
||||||
|
{
|
||||||
|
if (shift >= eSize)
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
long roundConst = 1L << (shift - 1);
|
||||||
|
|
||||||
|
long add = value + roundConst;
|
||||||
|
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
if ((~value & (value ^ add)) < 0L)
|
||||||
|
{
|
||||||
|
return (long)((ulong)add >> shift);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return add >> shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (eSize != 64) */
|
||||||
|
{
|
||||||
|
return add >> shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (!round) */
|
||||||
|
{
|
||||||
|
if (shift >= eSize)
|
||||||
|
{
|
||||||
|
if (value < 0L)
|
||||||
|
{
|
||||||
|
return -1L;
|
||||||
|
}
|
||||||
|
else /* if (value >= 0L) */
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value >> shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
|
||||||
|
{
|
||||||
|
if (round)
|
||||||
|
{
|
||||||
|
if (shift > 64)
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
long roundConst = 1L << (shift - 1);
|
||||||
|
|
||||||
|
ulong add = value + (ulong)roundConst;
|
||||||
|
|
||||||
|
if (eSize == 64)
|
||||||
|
{
|
||||||
|
if ((add < value) && (add < (ulong)roundConst))
|
||||||
|
{
|
||||||
|
if (shift == 64)
|
||||||
|
{
|
||||||
|
return 1UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (shift == 64)
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return add >> shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (eSize != 64) */
|
||||||
|
{
|
||||||
|
if (shift == 64)
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return add >> shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (!round) */
|
||||||
|
{
|
||||||
|
if (shift >= eSize)
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value >> shift;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long SignedSignSatQ(long op, int eSize, CpuThreadState state) // eSize := {8, 16, 32, 64}.
|
||||||
|
{
|
||||||
|
long tMaxValue = (1L << (eSize - 1)) - 1L;
|
||||||
|
long tMinValue = -(1L << (eSize - 1));
|
||||||
|
|
||||||
|
if (op > 0L)
|
||||||
|
{
|
||||||
|
state.SetFpsrFlag(Fpsr.Qc);
|
||||||
|
|
||||||
|
return tMaxValue;
|
||||||
|
}
|
||||||
|
else if (op < 0L)
|
||||||
|
{
|
||||||
|
state.SetFpsrFlag(Fpsr.Qc);
|
||||||
|
|
||||||
|
return tMinValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong UnsignedSignSatQ(ulong op, int eSize, CpuThreadState state) // eSize := {8, 16, 32, 64}.
|
||||||
|
{
|
||||||
|
ulong tMaxValue = ulong.MaxValue >> (64 - eSize);
|
||||||
|
|
||||||
|
if (op > 0UL)
|
||||||
|
{
|
||||||
|
state.SetFpsrFlag(Fpsr.Qc);
|
||||||
|
|
||||||
|
return tMaxValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0UL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
#region "ShrImm64"
|
#region "ShrImm64"
|
||||||
public static long SignedShrImm64(long value, long roundConst, int shift)
|
public static long SignedShrImm64(long value, long roundConst, int shift)
|
||||||
{
|
{
|
||||||
|
@ -31,7 +308,7 @@ namespace ChocolArm64.Instructions
|
||||||
{
|
{
|
||||||
return -1L;
|
return -1L;
|
||||||
}
|
}
|
||||||
else
|
else /* if (value >= 0L) */
|
||||||
{
|
{
|
||||||
return 0L;
|
return 0L;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue