This commit is contained in:
MS-DOS1999 2018-08-04 11:31:14 +00:00 committed by GitHub
commit 7cfea25021
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 29 deletions

View file

@ -374,6 +374,8 @@ namespace ChocolArm64
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<<1xxxxx101000xxxxxxxxxx", AInstEmit.Smlsl_V, typeof(AOpCodeSimdReg));
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg)); SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Smull_V, typeof(AOpCodeSimdReg));
SetA64("01011110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Sqadd_S, typeof(AOpCodeSimdReg));
SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Sqadd_V, typeof(AOpCodeSimdReg));
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_V, typeof(AOpCodeSimdShImm)); 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));
@ -423,6 +425,8 @@ namespace ChocolArm64
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Uminp_V, typeof(AOpCodeSimdReg)); SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Uminp_V, typeof(AOpCodeSimdReg));
SetA64("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns)); SetA64("0x001110000xxxxx001111xxxxxxxxxx", AInstEmit.Umov_S, typeof(AOpCodeSimdIns));
SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Umull_V, typeof(AOpCodeSimdReg)); SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", AInstEmit.Umull_V, typeof(AOpCodeSimdReg));
SetA64("01111110xx1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_S, typeof(AOpCodeSimdReg));
SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", AInstEmit.Uqadd_V, typeof(AOpCodeSimdReg));
SetA64("01111110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_S, typeof(AOpCodeSimd)); SetA64("01111110<<100001010010xxxxxxxxxx", AInstEmit.Uqxtn_S, typeof(AOpCodeSimd));
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));

View file

@ -1052,24 +1052,34 @@ namespace ChocolArm64.Instruction
EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul)); EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
} }
public static void Sqadd_S(AILEmitterCtx Context)
{
EmitScalarBinarySaturatingOpSxSx(Context, () => Context.Emit(OpCodes.Add));
}
public static void Sqadd_V(AILEmitterCtx Context)
{
EmitVectorBinarySaturatingOpSxSx(Context, () => Context.Emit(OpCodes.Add));
}
public static void Sqxtn_S(AILEmitterCtx Context) public static void Sqxtn_S(AILEmitterCtx Context)
{ {
EmitScalarSaturatingNarrowOpSxSx(Context, () => { }); EmitScalarUnarySaturatingNarrowOpSxSx(Context, () => { });
} }
public static void Sqxtn_V(AILEmitterCtx Context) public static void Sqxtn_V(AILEmitterCtx Context)
{ {
EmitVectorSaturatingNarrowOpSxSx(Context, () => { }); EmitVectorUnarySaturatingNarrowOpSxSx(Context, () => { });
} }
public static void Sqxtun_S(AILEmitterCtx Context) public static void Sqxtun_S(AILEmitterCtx Context)
{ {
EmitScalarSaturatingNarrowOpSxZx(Context, () => { }); EmitScalarUnarySaturatingNarrowOpSxZx(Context, () => { });
} }
public static void Sqxtun_V(AILEmitterCtx Context) public static void Sqxtun_V(AILEmitterCtx Context)
{ {
EmitVectorSaturatingNarrowOpSxZx(Context, () => { }); EmitVectorUnarySaturatingNarrowOpSxZx(Context, () => { });
} }
public static void Ssubw_V(AILEmitterCtx Context) public static void Ssubw_V(AILEmitterCtx Context)
@ -1221,14 +1231,24 @@ namespace ChocolArm64.Instruction
EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul)); EmitVectorWidenRnRmBinaryOpZx(Context, () => Context.Emit(OpCodes.Mul));
} }
public static void Uqadd_S(AILEmitterCtx Context)
{
EmitScalarBinarySaturatingOpZxZx(Context, () => Context.Emit(OpCodes.Add));
}
public static void Uqadd_V(AILEmitterCtx Context)
{
EmitVectorBinarySaturatingOpZxZx(Context, () => Context.Emit(OpCodes.Add));
}
public static void Uqxtn_S(AILEmitterCtx Context) public static void Uqxtn_S(AILEmitterCtx Context)
{ {
EmitScalarSaturatingNarrowOpZxZx(Context, () => { }); EmitScalarUnarySaturatingNarrowOpZxZx(Context, () => { });
} }
public static void Uqxtn_V(AILEmitterCtx Context) public static void Uqxtn_V(AILEmitterCtx Context)
{ {
EmitVectorSaturatingNarrowOpZxZx(Context, () => { }); EmitVectorUnarySaturatingNarrowOpZxZx(Context, () => { });
} }
public static void Usubw_V(AILEmitterCtx Context) public static void Usubw_V(AILEmitterCtx Context)

View file

@ -781,50 +781,121 @@ namespace ChocolArm64.Instruction
} }
} }
public static void EmitScalarSaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit) [Flags]
public enum SaturatingFlags
{ {
EmitSaturatingNarrowOp(Context, Emit, true, true, true); None = 0,
SignedSrc = 1 << 0,
SignedDst = 1 << 1,
Scalar = 1 << 2,
Narrow = 1 << 3,
Binary = 1 << 4,
SxSxScalarUnary = SignedSrc | SignedDst | Scalar,
SxSxScalarNarrowUnary = SignedSrc | SignedDst | Scalar | Narrow,
SxZxScalarUnary = SignedSrc | Scalar,
SxZxScalarNarrowUnary = SignedSrc | Scalar | Narrow,
ZxZxScalarUnary = Scalar,
ZxZxScalarNarrowUnary = Scalar | Narrow,
SxSxVectorUnary = SignedSrc | SignedDst,
SxSxVectorNarrowUnary = SignedSrc | SignedDst | Narrow,
SxZxVectorUnary = SignedSrc,
SxZxVectorNarrowUnary = SignedSrc | Narrow,
ZxZxVectorUnary = 0,
ZxZxVectorNarrowUnary = Narrow,
SxSxScalarBinary = SignedSrc | SignedDst | Scalar | Binary,
SxSxScalarNarrowBinary = SignedSrc | SignedDst | Scalar | Narrow | Binary,
SxZxScalarBinary = SignedSrc | Scalar | Binary,
SxZxScalarNarrowBinary = SignedSrc | Scalar | Narrow | Binary,
ZxZxScalarBinary = Scalar | Binary,
ZxZxScalarNarrowBinary = Scalar | Narrow | Binary,
SxSxVectorBinary = SignedSrc | SignedDst | Binary,
SxSxVectorNarrowBinary = SignedSrc | SignedDst | Narrow | Binary,
SxZxVectorBinary = SignedSrc | Binary,
SxZxVectorNarrowBinary = SignedSrc | Narrow | Binary,
ZxZxVectorBinary = Binary,
ZxZxVectorNarrowBinary = Narrow | Binary
} }
public static void EmitScalarSaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit) public static void EmitScalarBinarySaturatingOpSxSx(AILEmitterCtx Context, Action Emit)
{ {
EmitSaturatingNarrowOp(Context, Emit, true, false, true); EmitSaturatingOp(Context, Emit, SaturatingFlags.SxSxScalarBinary);
} }
public static void EmitScalarSaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit) public static void EmitScalarBinarySaturatingOpZxZx(AILEmitterCtx Context, Action Emit)
{ {
EmitSaturatingNarrowOp(Context, Emit, false, false, true); EmitSaturatingOp(Context, Emit, SaturatingFlags.ZxZxScalarBinary);
} }
public static void EmitVectorSaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit) public static void EmitVectorBinarySaturatingOpSxSx(AILEmitterCtx Context, Action Emit)
{ {
EmitSaturatingNarrowOp(Context, Emit, true, true, false); EmitSaturatingOp(Context, Emit, SaturatingFlags.SxSxVectorBinary);
} }
public static void EmitVectorSaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit) public static void EmitVectorBinarySaturatingOpZxZx(AILEmitterCtx Context, Action Emit)
{ {
EmitSaturatingNarrowOp(Context, Emit, true, false, false); EmitSaturatingOp(Context, Emit, SaturatingFlags.ZxZxVectorBinary);
} }
public static void EmitVectorSaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit) public static void EmitScalarUnarySaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit)
{ {
EmitSaturatingNarrowOp(Context, Emit, false, false, false); EmitSaturatingOp(Context, Emit, SaturatingFlags.SxSxScalarNarrowUnary);
} }
public static void EmitSaturatingNarrowOp( public static void EmitScalarUnarySaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit)
{
EmitSaturatingOp(Context, Emit, SaturatingFlags.SxZxScalarNarrowUnary);
}
public static void EmitScalarUnarySaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit)
{
EmitSaturatingOp(Context, Emit, SaturatingFlags.ZxZxScalarNarrowUnary);
}
public static void EmitVectorUnarySaturatingNarrowOpSxSx(AILEmitterCtx Context, Action Emit)
{
EmitSaturatingOp(Context, Emit, SaturatingFlags.SxSxVectorNarrowUnary);
}
public static void EmitVectorUnarySaturatingNarrowOpSxZx(AILEmitterCtx Context, Action Emit)
{
EmitSaturatingOp(Context, Emit, SaturatingFlags.SxZxVectorNarrowUnary);
}
public static void EmitVectorUnarySaturatingNarrowOpZxZx(AILEmitterCtx Context, Action Emit)
{
EmitSaturatingOp(Context, Emit, SaturatingFlags.ZxZxVectorNarrowUnary);
}
public static void EmitSaturatingOp(
AILEmitterCtx Context, AILEmitterCtx Context,
Action Emit, Action Emit,
bool SignedSrc, SaturatingFlags Flags)
bool SignedDst,
bool Scalar)
{ {
bool SignedSrc = (Flags & SaturatingFlags.SignedSrc) != 0;
bool SignedDst = (Flags & SaturatingFlags.SignedDst) != 0;
bool Scalar = (Flags & SaturatingFlags.Scalar) != 0;
bool Narrow = (Flags & SaturatingFlags.Narrow) != 0;
bool Binary = (Flags & SaturatingFlags.Binary) != 0;
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
int Elems = !Scalar ? 8 >> Op.Size : 1; int Bytes = Op.GetBitsCount() >> 3;
int Elems = !Scalar ? (Narrow ? 8 : Bytes) >> Op.Size : 1;
int ESize = 8 << Op.Size; int ESize = 8 << Op.Size;
int Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0; int Part = 0;
if (Narrow)
{
Part = !Scalar && (Op.RegisterSize == ARegisterSize.SIMD128) ? Elems : 0;
}
long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (long)(~0UL >> (64 - ESize)); long TMaxValue = SignedDst ? (1 << (ESize - 1)) - 1 : (long)(~0UL >> (64 - ESize));
long TMinValue = SignedDst ? -((1 << (ESize - 1))) : 0; long TMinValue = SignedDst ? -((1 << (ESize - 1))) : 0;
@ -832,7 +903,7 @@ namespace ChocolArm64.Instruction
Context.EmitLdc_I8(0L); Context.EmitLdc_I8(0L);
Context.EmitSttmp(); Context.EmitSttmp();
if (Part != 0) if (Part != 0 && Narrow)
{ {
Context.EmitLdvec(Op.Rd); Context.EmitLdvec(Op.Rd);
Context.EmitStvectmp(); Context.EmitStvectmp();
@ -843,7 +914,12 @@ namespace ChocolArm64.Instruction
AILLabel LblLe = new AILLabel(); AILLabel LblLe = new AILLabel();
AILLabel LblGeEnd = new AILLabel(); AILLabel LblGeEnd = new AILLabel();
EmitVectorExtract(Context, Op.Rn, Index, Op.Size + 1, SignedSrc); EmitVectorExtract(Context, Op.Rn, Index, Narrow ? Op.Size + 1 : Op.Size, SignedSrc);
if (Binary)
{
EmitVectorExtract(Context, ((AOpCodeSimdReg)Op).Rm, Index, Narrow ? Op.Size + 1 : Op.Size, SignedSrc);
}
Emit(); Emit();
@ -882,13 +958,13 @@ namespace ChocolArm64.Instruction
EmitVectorZeroLowerTmp(Context); EmitVectorZeroLowerTmp(Context);
} }
EmitVectorInsertTmp(Context, Part + Index, Op.Size); EmitVectorInsertTmp(Context, Narrow ? Index + Part : Index, Op.Size);
} }
Context.EmitLdvectmp(); Context.EmitLdvectmp();
Context.EmitStvec(Op.Rd); Context.EmitStvec(Op.Rd);
if (Part == 0) if ((Op.RegisterSize == ARegisterSize.SIMD64) || Scalar || (Part == 0 && Narrow))
{ {
EmitVectorZeroUpper(Context, Op.Rd); EmitVectorZeroUpper(Context, Op.Rd);
} }

View file

@ -100,7 +100,7 @@ namespace ChocolArm64.Instruction
Context.Emit(OpCodes.Shr); Context.Emit(OpCodes.Shr);
}; };
EmitVectorSaturatingNarrowOpSxSx(Context, Emit); EmitVectorUnarySaturatingNarrowOpSxSx(Context, Emit);
} }
public static void Srshr_V(AILEmitterCtx Context) public static void Srshr_V(AILEmitterCtx Context)

View file

@ -1126,6 +1126,19 @@ namespace Ryujinx.Tests.Cpu
}); });
} }
[TestCase(0x00000001u, 0x7FFFFFFFu, 0x7FFFFFFFu, true)]
public void Sqadd_S(uint A, uint B, uint Result, bool Fpsr)
{
Vector128<float> V1 = MakeVectorE0(A);
Vector128<float> V2 = MakeVectorE0(B);
AThreadState ThreadState = SingleOpcode(0x5EA20C20, V1: V1, V2: V2);
Assert.Multiple(() =>
{
Assert.AreEqual(Result, GetVectorE0(ThreadState.V0));
Assert.AreEqual(((ThreadState.Fpsr >> 27) & 1) == 1, Fpsr);
});
}
[Test, Description("SQXTN <Vb><d>, <Va><n>")] [Test, Description("SQXTN <Vb><d>, <Va><n>")]
public void Sqxtn_S_HB_SH_DS([Values(0u)] uint Rd, public void Sqxtn_S_HB_SH_DS([Values(0u)] uint Rd,
[Values(1u, 0u)] uint Rn, [Values(1u, 0u)] uint Rn,