mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-09 12:19:12 +00:00
Update Fork
This commit is contained in:
commit
3a0778711e
17 changed files with 360 additions and 195 deletions
|
@ -371,16 +371,22 @@ namespace ChocolArm64
|
||||||
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Sminp_V, typeof(AOpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Sminp_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", AInstEmit.Smlal_V, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", AInstEmit.Smlsl_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
|
||||||
|
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("01011110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_S, typeof(AOpCodeSimd));
|
SetA64("01011110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0x001110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_V, typeof(AOpCodeSimd));
|
SetA64("0x001110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_V, typeof(AOpCodeSimd));
|
||||||
SetA64("01111110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_S, typeof(AOpCodeSimd));
|
SetA64("01111110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_S, typeof(AOpCodeSimd));
|
||||||
SetA64("0x101110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_V, typeof(AOpCodeSimd));
|
SetA64("0x101110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_V, typeof(AOpCodeSimd));
|
||||||
|
SetA64("0x00111100>>>xxx001001xxxxxxxxxx", AInstEmit.Srshr_V, typeof(AOpCodeSimdShImm));
|
||||||
|
SetA64("0100111101xxxxxx001001xxxxxxxxxx", AInstEmit.Srshr_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Sshl_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
SetA64("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
SetA64("0101111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0x0011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
SetA64("0x00111100>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0x0011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
|
SetA64("0100111101xxxxxx000001xxxxxxxxxx", AInstEmit.Sshr_V, typeof(AOpCodeSimdShImm));
|
||||||
|
SetA64("0x00111100>>>xxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
|
||||||
|
SetA64("0100111101xxxxxx000101xxxxxxxxxx", AInstEmit.Ssra_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
|
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
|
||||||
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
|
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", AInstEmit.St__Vms, typeof(AOpCodeSimdMemMs));
|
||||||
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs));
|
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", AInstEmit.St__Vss, typeof(AOpCodeSimdMemSs));
|
||||||
|
@ -419,9 +425,11 @@ namespace ChocolArm64
|
||||||
SetA64("0x101110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_V, typeof(AOpCodeSimd));
|
SetA64("0x101110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_V, typeof(AOpCodeSimd));
|
||||||
SetA64("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx010001xxxxxxxxxx", AInstEmit.Ushl_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx101001xxxxxxxxxx", AInstEmit.Ushll_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("011111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm));
|
SetA64("0111111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_S, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0x1011110>>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0x1011110>>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
SetA64("0110111101xxxxxx000001xxxxxxxxxx", AInstEmit.Ushr_V, typeof(AOpCodeSimdShImm));
|
||||||
|
SetA64("0x10111100>>>xxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
||||||
|
SetA64("0110111101xxxxxx000101xxxxxxxxxx", AInstEmit.Usra_V, typeof(AOpCodeSimdShImm));
|
||||||
SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
|
SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", AInstEmit.Uzp1_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg));
|
SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", AInstEmit.Uzp2_V, typeof(AOpCodeSimdReg));
|
||||||
SetA64("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd));
|
SetA64("0x001110<<100001001010xxxxxxxxxx", AInstEmit.Xtn_V, typeof(AOpCodeSimd));
|
||||||
|
|
|
@ -65,11 +65,12 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
|
||||||
|
|
||||||
for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 1; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
||||||
|
|
||||||
|
@ -97,13 +98,16 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
int ESize = 8 << Op.Size;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
||||||
|
|
||||||
Context.EmitLdc_I4(8 << Op.Size);
|
Context.EmitLdc_I4(ESize);
|
||||||
|
|
||||||
Emit();
|
Emit();
|
||||||
|
|
||||||
|
@ -190,84 +194,6 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitSaturatingExtNarrow(AILEmitterCtx Context, bool SignedSrc, bool SignedDst, bool Scalar)
|
|
||||||
{
|
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
|
||||||
|
|
||||||
int Elems = (!Scalar ? 8 >> Op.Size : 1);
|
|
||||||
int ESize = 8 << Op.Size;
|
|
||||||
|
|
||||||
int Part = (!Scalar & (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0);
|
|
||||||
|
|
||||||
int TMaxValue = (SignedDst ? (1 << (ESize - 1)) - 1 : (int)((1L << ESize) - 1L));
|
|
||||||
int TMinValue = (SignedDst ? -((1 << (ESize - 1))) : 0);
|
|
||||||
|
|
||||||
Context.EmitLdc_I8(0L);
|
|
||||||
Context.EmitSttmp();
|
|
||||||
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
|
||||||
{
|
|
||||||
AILLabel LblLe = new AILLabel();
|
|
||||||
AILLabel LblGeEnd = new AILLabel();
|
|
||||||
|
|
||||||
EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Dup);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4(TMaxValue);
|
|
||||||
Context.Emit(OpCodes.Conv_U8);
|
|
||||||
|
|
||||||
Context.Emit(SignedSrc ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Pop);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4(TMaxValue);
|
|
||||||
|
|
||||||
Context.EmitLdc_I8(0x8000000L);
|
|
||||||
Context.EmitSttmp();
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Br_S, LblGeEnd);
|
|
||||||
|
|
||||||
Context.MarkLabel(LblLe);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Dup);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4(TMinValue);
|
|
||||||
Context.Emit(OpCodes.Conv_I8);
|
|
||||||
|
|
||||||
Context.Emit(SignedSrc ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd);
|
|
||||||
|
|
||||||
Context.Emit(OpCodes.Pop);
|
|
||||||
|
|
||||||
Context.EmitLdc_I4(TMinValue);
|
|
||||||
|
|
||||||
Context.EmitLdc_I8(0x8000000L);
|
|
||||||
Context.EmitSttmp();
|
|
||||||
|
|
||||||
Context.MarkLabel(LblGeEnd);
|
|
||||||
|
|
||||||
if (Scalar)
|
|
||||||
{
|
|
||||||
EmitVectorZeroLower(Context, Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Part == 0)
|
|
||||||
{
|
|
||||||
EmitVectorZeroUpper(Context, Op.Rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
|
||||||
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
|
||||||
Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr));
|
|
||||||
Context.EmitLdtmp();
|
|
||||||
Context.Emit(OpCodes.Conv_I4);
|
|
||||||
Context.Emit(OpCodes.Or);
|
|
||||||
Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Fabd_S(AILEmitterCtx Context)
|
public static void Fabd_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitScalarBinaryOpF(Context, () =>
|
EmitScalarBinaryOpF(Context, () =>
|
||||||
|
@ -338,7 +264,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int SizeF = Op.Size & 1;
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
int Elems = Bytes >> SizeF + 2;
|
int Elems = Bytes >> SizeF + 2;
|
||||||
int Half = Elems >> 1;
|
int Half = Elems >> 1;
|
||||||
|
@ -870,7 +796,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int SizeF = Op.Size & 1;
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
||||||
{
|
{
|
||||||
|
@ -1102,6 +1028,15 @@ namespace ChocolArm64.Instruction
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Smlsl_V(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
EmitVectorWidenRnRmTernaryOpSx(Context, () =>
|
||||||
|
{
|
||||||
|
Context.Emit(OpCodes.Mul);
|
||||||
|
Context.Emit(OpCodes.Sub);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static void Smull_V(AILEmitterCtx Context)
|
public static void Smull_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
|
EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
|
||||||
|
@ -1109,22 +1044,22 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Sqxtn_S(AILEmitterCtx Context)
|
public static void Sqxtn_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitSaturatingExtNarrow(Context, SignedSrc: true, SignedDst: true, Scalar: true);
|
EmitScalarSaturatingNarrowOpSxSx(Context, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sqxtn_V(AILEmitterCtx Context)
|
public static void Sqxtn_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitSaturatingExtNarrow(Context, SignedSrc: true, SignedDst: true, Scalar: false);
|
EmitVectorSaturatingNarrowOpSxSx(Context, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sqxtun_S(AILEmitterCtx Context)
|
public static void Sqxtun_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitSaturatingExtNarrow(Context, SignedSrc: true, SignedDst: false, Scalar: true);
|
EmitScalarSaturatingNarrowOpSxZx(Context, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sqxtun_V(AILEmitterCtx Context)
|
public static void Sqxtun_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitSaturatingExtNarrow(Context, SignedSrc: true, SignedDst: false, Scalar: false);
|
EmitVectorSaturatingNarrowOpSxZx(Context, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sub_S(AILEmitterCtx Context)
|
public static void Sub_S(AILEmitterCtx Context)
|
||||||
|
@ -1198,11 +1133,12 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, 0, Op.Size);
|
||||||
|
|
||||||
for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 1; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
||||||
|
|
||||||
|
@ -1272,12 +1208,12 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static void Uqxtn_S(AILEmitterCtx Context)
|
public static void Uqxtn_S(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitSaturatingExtNarrow(Context, SignedSrc: false, SignedDst: false, Scalar: true);
|
EmitScalarSaturatingNarrowOpZxZx(Context, () => { });
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Uqxtn_V(AILEmitterCtx Context)
|
public static void Uqxtn_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitSaturatingExtNarrow(Context, SignedSrc: false, SignedDst: false, Scalar: false);
|
EmitVectorSaturatingNarrowOpZxZx(Context, () => { });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -363,7 +363,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
int Elems = (!Scalar ? Bytes >> Op.Size : 1);
|
int Elems = (!Scalar ? Bytes >> Op.Size : 1);
|
||||||
|
|
||||||
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
||||||
|
@ -407,7 +407,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
int Elems = (!Scalar ? Bytes >> Op.Size : 1);
|
int Elems = (!Scalar ? Bytes >> Op.Size : 1);
|
||||||
|
|
||||||
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
ulong SzMask = ulong.MaxValue >> (64 - (8 << Op.Size));
|
||||||
|
@ -454,7 +454,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int SizeF = Op.Size & 1;
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
for (int Index = 0; Index < Bytes >> SizeF + 2; Index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -337,7 +337,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int FBits = GetFBits(Context);
|
int FBits = GetFBits(Context);
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> SizeI); Index++)
|
for (int Index = 0; Index < (Bytes >> SizeI); Index++)
|
||||||
{
|
{
|
||||||
|
@ -426,7 +426,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int FBits = GetFBits(Context);
|
int FBits = GetFBits(Context);
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> SizeI); Index++)
|
for (int Index = 0; Index < (Bytes >> SizeI); Index++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@ using ChocolArm64.State;
|
||||||
using ChocolArm64.Translation;
|
using ChocolArm64.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.Intrinsics;
|
using System.Runtime.Intrinsics;
|
||||||
using System.Runtime.Intrinsics.X86;
|
using System.Runtime.Intrinsics.X86;
|
||||||
|
@ -417,7 +418,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int SizeF = Op.Size & 1;
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++)
|
for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++)
|
||||||
{
|
{
|
||||||
|
@ -467,7 +468,7 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
int SizeF = Op.Size & 1;
|
int SizeF = Op.Size & 1;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++)
|
for (int Index = 0; Index < (Bytes >> SizeF + 2); Index++)
|
||||||
{
|
{
|
||||||
|
@ -527,9 +528,10 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
if (Opers.HasFlag(OperFlags.Rd))
|
if (Opers.HasFlag(OperFlags.Rd))
|
||||||
{
|
{
|
||||||
|
@ -582,9 +584,10 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
if (Ternary)
|
if (Ternary)
|
||||||
{
|
{
|
||||||
|
@ -622,9 +625,10 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
|
AOpCodeSimdImm Op = (AOpCodeSimdImm)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
if (Binary)
|
if (Binary)
|
||||||
{
|
{
|
||||||
|
@ -739,11 +743,11 @@ namespace ChocolArm64.Instruction
|
||||||
EmitVectorPairwiseOp(Context, Emit, false);
|
EmitVectorPairwiseOp(Context, Emit, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorPairwiseOp(AILEmitterCtx Context, Action Emit, bool Signed)
|
public static void EmitVectorPairwiseOp(AILEmitterCtx Context, Action Emit, bool Signed)
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
int Elems = Bytes >> Op.Size;
|
int Elems = Bytes >> Op.Size;
|
||||||
int Half = Elems >> 1;
|
int Half = Elems >> 1;
|
||||||
|
@ -769,6 +773,117 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void EmitScalarSaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitSaturatingNarrowOp(Context, Emit, true, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitScalarSaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitSaturatingNarrowOp(Context, Emit, true, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitScalarSaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitSaturatingNarrowOp(Context, Emit, false, false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorSaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitSaturatingNarrowOp(Context, Emit, true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorSaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitSaturatingNarrowOp(Context, Emit, true, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitVectorSaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit)
|
||||||
|
{
|
||||||
|
EmitSaturatingNarrowOp(Context, Emit, false, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void EmitSaturatingNarrowOp(
|
||||||
|
AILEmitterCtx Context,
|
||||||
|
Action Emit,
|
||||||
|
bool SignedSrc,
|
||||||
|
bool SignedDst,
|
||||||
|
bool Scalar)
|
||||||
|
{
|
||||||
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
|
int Elems = !Scalar ? 8 >> Op.Size : 1;
|
||||||
|
int ESize = 8 << Op.Size;
|
||||||
|
|
||||||
|
int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0;
|
||||||
|
|
||||||
|
long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (1L << ESize) - 1L;
|
||||||
|
long TMinValue = SignedDst ? -((1 << (ESize - 1))) : 0;
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(0L);
|
||||||
|
Context.EmitSttmp();
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
|
{
|
||||||
|
AILLabel LblLe = new AILLabel();
|
||||||
|
AILLabel LblGeEnd = new AILLabel();
|
||||||
|
|
||||||
|
EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc);
|
||||||
|
|
||||||
|
Emit();
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Dup);
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(TMaxValue);
|
||||||
|
|
||||||
|
Context.Emit(SignedSrc ? OpCodes.Ble_S : OpCodes.Ble_Un_S, LblLe);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Pop);
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(TMaxValue);
|
||||||
|
Context.EmitLdc_I8(0x8000000L);
|
||||||
|
Context.EmitSttmp();
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Br_S, LblGeEnd);
|
||||||
|
|
||||||
|
Context.MarkLabel(LblLe);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Dup);
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(TMinValue);
|
||||||
|
|
||||||
|
Context.Emit(SignedSrc ? OpCodes.Bge_S : OpCodes.Bge_Un_S, LblGeEnd);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Pop);
|
||||||
|
|
||||||
|
Context.EmitLdc_I8(TMinValue);
|
||||||
|
Context.EmitLdc_I8(0x8000000L);
|
||||||
|
Context.EmitSttmp();
|
||||||
|
|
||||||
|
Context.MarkLabel(LblGeEnd);
|
||||||
|
|
||||||
|
if (Scalar)
|
||||||
|
{
|
||||||
|
EmitVectorZeroLower(Context, Op.Rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmitVectorInsert(Context, Op.Rd, Part + Index, Op.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Part == 0)
|
||||||
|
{
|
||||||
|
EmitVectorZeroUpper(Context, Op.Rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||||
|
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
|
||||||
|
Context.EmitCallPropGet(typeof(AThreadState), nameof(AThreadState.Fpsr));
|
||||||
|
Context.EmitLdtmp();
|
||||||
|
Context.Emit(OpCodes.Conv_I4);
|
||||||
|
Context.Emit(OpCodes.Or);
|
||||||
|
Context.EmitCallPropSet(typeof(AThreadState), nameof(AThreadState.Fpsr));
|
||||||
|
}
|
||||||
|
|
||||||
public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
|
public static void EmitScalarSet(AILEmitterCtx Context, int Reg, int Size)
|
||||||
{
|
{
|
||||||
EmitVectorZeroAll(Context, Reg);
|
EmitVectorZeroAll(Context, Reg);
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
int Elems = Bytes >> Op.Size;
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < Elems; Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
|
@ -195,7 +195,7 @@ namespace ChocolArm64.Instruction
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
int Elems = Bytes >> Op.Size;
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1;
|
int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1;
|
||||||
|
|
|
@ -105,13 +105,14 @@ namespace ChocolArm64.Instruction
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int SElem = 0; SElem < Op.SElems; SElem++)
|
for (int SElem = 0; SElem < Op.SElems; SElem++)
|
||||||
{
|
{
|
||||||
int Rt = (Op.Rt + SElem) & 0x1f;
|
int Rt = (Op.Rt + SElem) & 0x1f;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitMemAddress();
|
EmitMemAddress();
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,10 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
|
AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
Context.EmitLdintzr(Op.Rn);
|
Context.EmitLdintzr(Op.Rn);
|
||||||
|
|
||||||
|
@ -42,9 +43,10 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
|
AOpCodeSimdIns Op = (AOpCodeSimdIns)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, Op.DstIndex, Op.Size);
|
||||||
|
|
||||||
|
@ -64,7 +66,7 @@ namespace ChocolArm64.Instruction
|
||||||
Context.EmitLdvec(Op.Rd);
|
Context.EmitLdvec(Op.Rd);
|
||||||
Context.EmitStvectmp();
|
Context.EmitStvectmp();
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
int Position = Op.Imm4;
|
int Position = Op.Imm4;
|
||||||
|
|
||||||
|
@ -329,7 +331,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
int Elems = Bytes >> Op.Size;
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
|
@ -355,7 +357,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
int Elems = Bytes >> Op.Size;
|
int Elems = Bytes >> Op.Size;
|
||||||
int Half = Elems >> 1;
|
int Half = Elems >> 1;
|
||||||
|
@ -382,7 +384,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
|
||||||
int Elems = Bytes >> Op.Size;
|
int Elems = Bytes >> Op.Size;
|
||||||
int Half = Elems >> 1;
|
int Half = Elems >> 1;
|
||||||
|
|
|
@ -27,9 +27,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Shift = Op.Imm - (8 << Op.Size);
|
EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
|
||||||
|
|
||||||
EmitVectorShImmBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shll_V(AILEmitterCtx Context)
|
public static void Shll_V(AILEmitterCtx Context)
|
||||||
|
@ -45,22 +43,21 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
|
EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), GetImmShr(Op));
|
||||||
|
|
||||||
EmitVectorShImmNarrowBinaryZx(Context, () => Context.Emit(OpCodes.Shr_Un), Shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sli_V(AILEmitterCtx Context)
|
public static void Sli_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
int Shift = Op.Imm - (8 << Op.Size);
|
int Shift = GetImmShl(Op);
|
||||||
|
|
||||||
ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0;
|
ulong Mask = Shift != 0 ? ulong.MaxValue >> (64 - Shift) : 0;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
|
||||||
|
|
||||||
|
@ -84,6 +81,39 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Sqrshrn_V(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
|
int Shift = GetImmShr(Op);
|
||||||
|
|
||||||
|
long RoundConst = 1L << (Shift - 1);
|
||||||
|
|
||||||
|
Action Emit = () =>
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I8(RoundConst);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
|
||||||
|
Context.EmitLdc_I4(Shift);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Shr);
|
||||||
|
};
|
||||||
|
|
||||||
|
EmitVectorSaturatingNarrowOpSxSx(Context, Emit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Srshr_V(AILEmitterCtx Context)
|
||||||
|
{
|
||||||
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
|
int Shift = GetImmShr(Op);
|
||||||
|
|
||||||
|
long RoundConst = 1L << (Shift - 1);
|
||||||
|
|
||||||
|
EmitVectorRoundShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift, RoundConst);
|
||||||
|
}
|
||||||
|
|
||||||
public static void Sshl_V(AILEmitterCtx Context)
|
public static void Sshl_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
EmitVectorShl(Context, Signed: true);
|
EmitVectorShl(Context, Signed: true);
|
||||||
|
@ -93,9 +123,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Shift = Op.Imm - (8 << Op.Size);
|
EmitVectorShImmWidenBinarySx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
|
||||||
|
|
||||||
EmitVectorShImmWidenBinarySx(Context, () => Context.Emit(OpCodes.Shl), Shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Sshr_S(AILEmitterCtx Context)
|
public static void Sshr_S(AILEmitterCtx Context)
|
||||||
|
@ -115,24 +143,20 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
|
EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), GetImmShr(Op));
|
||||||
|
|
||||||
EmitVectorShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ssra_V(AILEmitterCtx Context)
|
public static void Ssra_V(AILEmitterCtx Context)
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
|
|
||||||
|
|
||||||
Action Emit = () =>
|
Action Emit = () =>
|
||||||
{
|
{
|
||||||
Context.Emit(OpCodes.Shr);
|
Context.Emit(OpCodes.Shr);
|
||||||
Context.Emit(OpCodes.Add);
|
Context.Emit(OpCodes.Add);
|
||||||
};
|
};
|
||||||
|
|
||||||
EmitVectorShImmTernarySx(Context, Emit, Shift);
|
EmitVectorShImmTernarySx(Context, Emit, GetImmShr(Op));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ushl_V(AILEmitterCtx Context)
|
public static void Ushl_V(AILEmitterCtx Context)
|
||||||
|
@ -144,9 +168,7 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||||
|
|
||||||
int Shift = Op.Imm - (8 << Op.Size);
|
EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), GetImmShl(Op));
|
||||||
|
|
||||||
EmitVectorShImmWidenBinaryZx(Context, () => Context.Emit(OpCodes.Shl), Shift);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Ushr_S(AILEmitterCtx Context)
|
public static void Ushr_S(AILEmitterCtx Context)
|
||||||
|
@ -251,28 +273,51 @@ namespace ChocolArm64.Instruction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
private enum ShImmFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
Signed = 1 << 0,
|
||||||
|
Ternary = 1 << 1,
|
||||||
|
Rounded = 1 << 2,
|
||||||
|
|
||||||
|
SignedTernary = Signed | Ternary,
|
||||||
|
SignedRounded = Signed | Rounded
|
||||||
|
}
|
||||||
|
|
||||||
private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
private static void EmitVectorShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
||||||
{
|
{
|
||||||
EmitVectorShImmOp(Context, Emit, Imm, false, true);
|
EmitVectorShImmOp(Context, Emit, Imm, ShImmFlags.Signed);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorShImmTernarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
private static void EmitVectorShImmTernarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
||||||
{
|
{
|
||||||
EmitVectorShImmOp(Context, Emit, Imm, true, true);
|
EmitVectorShImmOp(Context, Emit, Imm, ShImmFlags.SignedTernary);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
|
private static void EmitVectorShImmBinaryZx(AILEmitterCtx Context, Action Emit, int Imm)
|
||||||
{
|
{
|
||||||
EmitVectorShImmOp(Context, Emit, Imm, false, false);
|
EmitVectorShImmOp(Context, Emit, Imm, ShImmFlags.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void EmitVectorShImmOp(AILEmitterCtx Context, Action Emit, int Imm, bool Ternary, bool Signed)
|
private static void EmitVectorRoundShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm, long Rc)
|
||||||
|
{
|
||||||
|
EmitVectorShImmOp(Context, Emit, Imm, ShImmFlags.SignedRounded, Rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void EmitVectorShImmOp(AILEmitterCtx Context, Action Emit, int Imm, ShImmFlags Flags, long Rc = 0)
|
||||||
{
|
{
|
||||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||||
|
|
||||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
int Bytes = Op.GetBitsCount() >> 3;
|
||||||
|
int Elems = Bytes >> Op.Size;
|
||||||
|
|
||||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
bool Signed = (Flags & ShImmFlags.Signed) != 0;
|
||||||
|
bool Ternary = (Flags & ShImmFlags.Ternary) != 0;
|
||||||
|
bool Rounded = (Flags & ShImmFlags.Rounded) != 0;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Elems; Index++)
|
||||||
{
|
{
|
||||||
if (Ternary)
|
if (Ternary)
|
||||||
{
|
{
|
||||||
|
@ -281,6 +326,13 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
|
EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
|
||||||
|
|
||||||
|
if (Rounded)
|
||||||
|
{
|
||||||
|
Context.EmitLdc_I8(Rc);
|
||||||
|
|
||||||
|
Context.Emit(OpCodes.Add);
|
||||||
|
}
|
||||||
|
|
||||||
Context.EmitLdc_I4(Imm);
|
Context.EmitLdc_I4(Imm);
|
||||||
|
|
||||||
Emit();
|
Emit();
|
||||||
|
|
|
@ -12,22 +12,42 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static ulong CountLeadingSigns(ulong Value, int Size)
|
public static ulong CountLeadingSigns(ulong Value, int Size)
|
||||||
{
|
{
|
||||||
return CountLeadingZeros((Value >> 1) ^ Value, Size - 1);
|
Value ^= Value >> 1;
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong CountLeadingZeros(ulong Value, int Size)
|
int HighBit = Size - 2;
|
||||||
{
|
|
||||||
int HighBit = Size - 1;
|
|
||||||
|
|
||||||
for (int Bit = HighBit; Bit >= 0; Bit--)
|
for (int Bit = HighBit; Bit >= 0; Bit--)
|
||||||
{
|
{
|
||||||
if (((Value >> Bit) & 1) != 0)
|
if (((Value >> Bit) & 0b1) != 0)
|
||||||
{
|
{
|
||||||
return (ulong)(HighBit - Bit);
|
return (ulong)(HighBit - Bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ulong)Size;
|
return (ulong)(Size - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
|
public static ulong CountLeadingZeros(ulong Value, int Size)
|
||||||
|
{
|
||||||
|
if (Value == 0)
|
||||||
|
{
|
||||||
|
return (ulong)Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int NibbleIdx = Size;
|
||||||
|
int PreCount, Count = 0;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
NibbleIdx -= 4;
|
||||||
|
PreCount = ClzNibbleTbl[(Value >> NibbleIdx) & 0b1111];
|
||||||
|
Count += PreCount;
|
||||||
|
}
|
||||||
|
while (PreCount == 4);
|
||||||
|
|
||||||
|
return (ulong)Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static uint CountSetBits8(uint Value)
|
public static uint CountSetBits8(uint Value)
|
||||||
|
@ -61,8 +81,8 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
private static uint Crc32w(uint Crc, uint Poly, uint Val)
|
private static uint Crc32w(uint Crc, uint Poly, uint Val)
|
||||||
{
|
{
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 0 ));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 8 ));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
|
||||||
|
|
||||||
|
@ -71,8 +91,8 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
private static uint Crc32x(uint Crc, uint Poly, ulong Val)
|
private static uint Crc32x(uint Crc, uint Poly, ulong Val)
|
||||||
{
|
{
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 0));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 0 ));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 8));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 8 ));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 16));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 24));
|
||||||
Crc = Crc32(Crc, Poly, (byte)(Val >> 32));
|
Crc = Crc32(Crc, Poly, (byte)(Val >> 32));
|
||||||
|
@ -168,9 +188,10 @@ namespace ChocolArm64.Instruction
|
||||||
|
|
||||||
public static long SMulHi128(long LHS, long RHS)
|
public static long SMulHi128(long LHS, long RHS)
|
||||||
{
|
{
|
||||||
long Result = (long)UMulHi128((ulong)(LHS), (ulong)(RHS));
|
long Result = (long)UMulHi128((ulong)LHS, (ulong)RHS);
|
||||||
if (LHS < 0) Result -= RHS;
|
if (LHS < 0) Result -= RHS;
|
||||||
if (RHS < 0) Result -= LHS;
|
if (RHS < 0) Result -= LHS;
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +208,7 @@ namespace ChocolArm64.Instruction
|
||||||
ulong Z1 = T & 0xFFFFFFFF;
|
ulong Z1 = T & 0xFFFFFFFF;
|
||||||
ulong Z0 = T >> 32;
|
ulong Z0 = T >> 32;
|
||||||
Z1 += LLow * RHigh;
|
Z1 += LLow * RHigh;
|
||||||
|
|
||||||
return LHigh * RHigh + Z0 + (Z1 >> 32);
|
return LHigh * RHigh + Z0 + (Z1 >> 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace Ryujinx.Graphics.Gal
|
||||||
|
|
||||||
void Bind(long Key);
|
void Bind(long Key);
|
||||||
|
|
||||||
|
void Unbind(GalShaderType Type);
|
||||||
|
|
||||||
void BindProgram();
|
void BindProgram();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -203,6 +203,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Unbind(GalShaderType Type)
|
||||||
|
{
|
||||||
|
switch (Type)
|
||||||
|
{
|
||||||
|
case GalShaderType.Vertex: Current.Vertex = null; break;
|
||||||
|
case GalShaderType.TessControl: Current.TessControl = null; break;
|
||||||
|
case GalShaderType.TessEvaluation: Current.TessEvaluation = null; break;
|
||||||
|
case GalShaderType.Geometry: Current.Geometry = null; break;
|
||||||
|
case GalShaderType.Fragment: Current.Fragment = null; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void BindProgram()
|
public void BindProgram()
|
||||||
{
|
{
|
||||||
if (Current.Vertex == null ||
|
if (Current.Vertex == null ||
|
||||||
|
|
|
@ -216,7 +216,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
private void PrintDeclOutAttributes()
|
private void PrintDeclOutAttributes()
|
||||||
{
|
{
|
||||||
if (Decl.ShaderType == GalShaderType.Vertex)
|
if (Decl.ShaderType != GalShaderType.Fragment)
|
||||||
{
|
{
|
||||||
SB.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") out vec4 " + GlslDecl.PositionOutAttrName + ";");
|
SB.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") out vec4 " + GlslDecl.PositionOutAttrName + ";");
|
||||||
}
|
}
|
||||||
|
@ -337,7 +337,10 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
if (Decl.ShaderType == GalShaderType.Vertex)
|
if (Decl.ShaderType == GalShaderType.Vertex)
|
||||||
{
|
{
|
||||||
SB.AppendLine(IdentationStr + "gl_Position.xy *= " + GlslDecl.FlipUniformName + ";");
|
SB.AppendLine(IdentationStr + "gl_Position.xy *= " + GlslDecl.FlipUniformName + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Decl.ShaderType != GalShaderType.Fragment)
|
||||||
|
{
|
||||||
SB.AppendLine(IdentationStr + GlslDecl.PositionOutAttrName + " = gl_Position;");
|
SB.AppendLine(IdentationStr + GlslDecl.PositionOutAttrName + " = gl_Position;");
|
||||||
SB.AppendLine(IdentationStr + GlslDecl.PositionOutAttrName + ".w = 1;");
|
SB.AppendLine(IdentationStr + GlslDecl.PositionOutAttrName + ".w = 1;");
|
||||||
}
|
}
|
||||||
|
@ -598,9 +601,6 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
{
|
{
|
||||||
switch (Op.Inst)
|
switch (Op.Inst)
|
||||||
{
|
{
|
||||||
case ShaderIrInst.Frcp:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case ShaderIrInst.Ipa:
|
case ShaderIrInst.Ipa:
|
||||||
case ShaderIrInst.Texq:
|
case ShaderIrInst.Texq:
|
||||||
case ShaderIrInst.Texs:
|
case ShaderIrInst.Texs:
|
||||||
|
@ -608,8 +608,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Op.OperandB != null ||
|
return true;
|
||||||
Op.OperandC != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetName(ShaderIrOperCbuf Cbuf)
|
private string GetName(ShaderIrOperCbuf Cbuf)
|
||||||
|
@ -711,13 +710,13 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Imm.Value.ToString(CultureInfo.InvariantCulture);
|
return GetIntConst(Imm.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetValue(ShaderIrOperImmf Immf)
|
private string GetValue(ShaderIrOperImmf Immf)
|
||||||
{
|
{
|
||||||
return Immf.Value.ToString(CultureInfo.InvariantCulture);
|
return GetFloatConst(Immf.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetName(ShaderIrOperPred Pred)
|
private string GetName(ShaderIrOperPred Pred)
|
||||||
|
@ -1047,7 +1046,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
if (!float.IsNaN(Value) && !float.IsInfinity(Value))
|
if (!float.IsNaN(Value) && !float.IsInfinity(Value))
|
||||||
{
|
{
|
||||||
return Value.ToString(CultureInfo.InvariantCulture);
|
return GetFloatConst(Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1064,6 +1063,20 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
return Expr;
|
return Expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string GetIntConst(int Value)
|
||||||
|
{
|
||||||
|
string Expr = Value.ToString(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
return Value < 0 ? "(" + Expr + ")" : Expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetFloatConst(float Value)
|
||||||
|
{
|
||||||
|
string Expr = Value.ToString(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
return Value < 0 ? "(" + Expr + ")" : Expr;
|
||||||
|
}
|
||||||
|
|
||||||
private static OperType GetDstNodeType(ShaderIrNode Node)
|
private static OperType GetDstNodeType(ShaderIrNode Node)
|
||||||
{
|
{
|
||||||
//Special case instructions with the result type different
|
//Special case instructions with the result type different
|
||||||
|
|
|
@ -172,6 +172,8 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
|
|
||||||
for (; Index < 6; Index++)
|
for (; Index < 6; Index++)
|
||||||
{
|
{
|
||||||
|
GalShaderType Type = GetTypeFromProgram(Index);
|
||||||
|
|
||||||
int Control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + Index * 0x10);
|
int Control = ReadRegister(NvGpuEngine3dReg.ShaderNControl + Index * 0x10);
|
||||||
int Offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + Index * 0x10);
|
int Offset = ReadRegister(NvGpuEngine3dReg.ShaderNOffset + Index * 0x10);
|
||||||
|
|
||||||
|
@ -180,16 +182,16 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
|
|
||||||
if (!Enable)
|
if (!Enable)
|
||||||
{
|
{
|
||||||
|
Gpu.Renderer.Shader.Unbind(Type);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
long Key = BasePosition + (uint)Offset;
|
long Key = BasePosition + (uint)Offset;
|
||||||
|
|
||||||
GalShaderType ShaderType = GetTypeFromProgram(Index);
|
Keys[(int)Type] = Key;
|
||||||
|
|
||||||
Keys[(int)ShaderType] = Key;
|
Gpu.Renderer.Shader.Create(Vmm, Key, Type);
|
||||||
|
|
||||||
Gpu.Renderer.Shader.Create(Vmm, Key, ShaderType);
|
|
||||||
Gpu.Renderer.Shader.Bind(Key);
|
Gpu.Renderer.Shader.Bind(Key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
|
||||||
|
|
||||||
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
KThread CurrThread = Process.GetThread(ThreadState.Tpidr);
|
||||||
|
|
||||||
if (TimeoutNs == 0)
|
if (TimeoutNs == 0 || TimeoutNs == ulong.MaxValue)
|
||||||
{
|
{
|
||||||
Process.Scheduler.Yield(CurrThread);
|
Process.Scheduler.Yield(CurrThread);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue