Add SMLSL, SQRSHRN and SRSHR (Vector) cpu instructions
This commit is contained in:
parent
97ca974213
commit
6e4aeff9e2
4 changed files with 198 additions and 86 deletions
|
@ -371,11 +371,15 @@ namespace ChocolArm64
|
|||
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", AInstEmit.Smin_V, typeof(AOpCodeSimdReg));
|
||||
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", AInstEmit.Sminp_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("0x00111100>>>xxx100111xxxxxxxxxx", AInstEmit.Sqrshrn_V, typeof(AOpCodeSimdShImm));
|
||||
SetA64("01011110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_S, typeof(AOpCodeSimd));
|
||||
SetA64("0x001110<<100001010010xxxxxxxxxx", AInstEmit.Sqxtn_V, typeof(AOpCodeSimd));
|
||||
SetA64("01111110<<100001001010xxxxxxxxxx", AInstEmit.Sqxtun_S, 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("0x00111100>>>xxx101001xxxxxxxxxx", AInstEmit.Sshll_V, typeof(AOpCodeSimdShImm));
|
||||
SetA64("010111110>>>>xxx000001xxxxxxxxxx", AInstEmit.Sshr_S, typeof(AOpCodeSimdShImm));
|
||||
|
|
|
@ -190,84 +190,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, () =>
|
||||
|
@ -1174,6 +1096,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));
|
||||
|
@ -1181,22 +1112,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)
|
||||
|
@ -1344,12 +1275,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, () => { });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ using ChocolArm64.State;
|
|||
using ChocolArm64.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Runtime.Intrinsics.X86;
|
||||
|
@ -719,7 +720,7 @@ namespace ChocolArm64.Instruction
|
|||
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;
|
||||
|
||||
|
@ -749,6 +750,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)
|
||||
{
|
||||
EmitVectorZeroAll(Context, Reg);
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace ChocolArm64.Instruction
|
|||
|
||||
int Shift = Op.Imm - (8 << Op.Size);
|
||||
|
||||
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++)
|
||||
{
|
||||
|
@ -84,6 +84,39 @@ namespace ChocolArm64.Instruction
|
|||
}
|
||||
}
|
||||
|
||||
public static void Sqrshrn_V(AILEmitterCtx Context)
|
||||
{
|
||||
AOpCodeSimdShImm Op = (AOpCodeSimdShImm)Context.CurrOp;
|
||||
|
||||
int Shift = (8 << (Op.Size + 1)) - Op.Imm;
|
||||
|
||||
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 = (8 << (Op.Size + 1)) - Op.Imm;
|
||||
|
||||
long RoundConst = 1L << (Shift - 1);
|
||||
|
||||
EmitVectorRoundShImmBinarySx(Context, () => Context.Emit(OpCodes.Shr), Shift, RoundConst);
|
||||
}
|
||||
|
||||
public static void Sshl_V(AILEmitterCtx Context)
|
||||
{
|
||||
EmitVectorShl(Context, Signed: true);
|
||||
|
@ -294,6 +327,38 @@ namespace ChocolArm64.Instruction
|
|||
}
|
||||
}
|
||||
|
||||
private static void EmitVectorRoundShImmBinarySx(AILEmitterCtx Context, Action Emit, int Imm, long Rc)
|
||||
{
|
||||
EmitVectorRoundShImmOp(Context, Emit, Imm, Rc, true);
|
||||
}
|
||||
|
||||
private static void EmitVectorRoundShImmOp(AILEmitterCtx Context, Action Emit, int Imm, long Rc, bool Signed)
|
||||
{
|
||||
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
|
||||
|
||||
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
|
||||
|
||||
for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
|
||||
{
|
||||
EmitVectorExtract(Context, Op.Rn, Index, Op.Size, Signed);
|
||||
|
||||
Context.EmitLdc_I8(Rc);
|
||||
|
||||
Context.Emit(OpCodes.Add);
|
||||
|
||||
Context.EmitLdc_I4(Imm);
|
||||
|
||||
Emit();
|
||||
|
||||
EmitVectorInsert(Context, Op.Rd, Index, Op.Size);
|
||||
}
|
||||
|
||||
if (Op.RegisterSize == ARegisterSize.SIMD64)
|
||||
{
|
||||
EmitVectorZeroUpper(Context, Op.Rd);
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitVectorShImmNarrowBinarySx(AILEmitterCtx Context, Action Emit, int Imm)
|
||||
{
|
||||
EmitVectorShImmNarrowBinaryOp(Context, Emit, Imm, true);
|
||||
|
|
Loading…
Add table
Reference in a new issue