Add SMLSL, SQRSHRN and SRSHR (Vector) cpu instructions, nits (#225)

* Add SMLSL, SQRSHRN and SRSHR (Vector) cpu instructions

* Address PR feedback

* Address PR feedback

* Remove another useless temp var

* nit: Alignment

* Replace Context.CurrOp.GetBitsCount() with Op.GetBitsCount()

* Fix encodings and move flag bit test out of the loop
This commit is contained in:
gdkchan 2018-07-14 13:13:02 -03:00 committed by GitHub
parent 2f37583ab3
commit 514218ab98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 265 additions and 153 deletions

View file

@ -65,11 +65,12 @@ namespace ChocolArm64.Instruction
{
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);
for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
for (int Index = 1; Index < Elems; Index++)
{
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
@ -97,9 +98,10 @@ namespace ChocolArm64.Instruction
{
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++)
{
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
@ -190,84 +192,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)
{
EmitScalarBinaryOpF(Context, () =>
@ -338,7 +262,7 @@ namespace ChocolArm64.Instruction
int SizeF = Op.Size & 1;
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
int Bytes = Op.GetBitsCount() >> 3;
int Elems = Bytes >> SizeF + 2;
int Half = Elems >> 1;
@ -870,7 +794,7 @@ namespace ChocolArm64.Instruction
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++)
{
@ -1102,6 +1026,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)
{
EmitVectorWidenRnRmBinaryOpSx(Context, () => Context.Emit(OpCodes.Mul));
@ -1109,22 +1042,22 @@ namespace ChocolArm64.Instruction
public static void Sqxtn_S(AILEmitterCtx Context)
{
EmitSaturatingExtNarrow(Context, SignedSrc: true, SignedDst: true, Scalar: true);
EmitScalarSaturatingNarrowOpSxSx(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)
{
EmitSaturatingExtNarrow(Context, SignedSrc: true, SignedDst: false, Scalar: true);
EmitScalarSaturatingNarrowOpSxZx(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)
@ -1198,11 +1131,12 @@ namespace ChocolArm64.Instruction
{
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);
for (int Index = 1; Index < (Bytes >> Op.Size); Index++)
for (int Index = 1; Index < Elems; Index++)
{
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
@ -1272,12 +1206,12 @@ namespace ChocolArm64.Instruction
public static void Uqxtn_S(AILEmitterCtx Context)
{
EmitSaturatingExtNarrow(Context, SignedSrc: false, SignedDst: false, Scalar: true);
EmitScalarSaturatingNarrowOpZxZx(Context, () => { });
}
public static void Uqxtn_V(AILEmitterCtx Context)
{
EmitSaturatingExtNarrow(Context, SignedSrc: false, SignedDst: false, Scalar: false);
EmitVectorSaturatingNarrowOpZxZx(Context, () => { });
}
}
}