0
0
Fork 0

Add REV16/32 (vector) instructions and fix REV64

This commit is contained in:
gdkchan 2018-06-25 18:40:55 -03:00
parent 8f4cd35ade
commit 37a6e84fd4
2 changed files with 31 additions and 3 deletions

View file

@ -347,6 +347,8 @@ namespace ChocolArm64
SetA64("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg)); SetA64("0x001110101xxxxx000111xxxxxxxxxx", AInstEmit.Orr_V, typeof(AOpCodeSimdReg));
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm)); SetA64("0x00111100000xxx<<x101xxxxxxxxxx", AInstEmit.Orr_Vi, typeof(AOpCodeSimdImm));
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Raddhn_V, typeof(AOpCodeSimdReg)); SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", AInstEmit.Raddhn_V, typeof(AOpCodeSimdReg));
SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd));
SetA64("0x1011100x100000000010xxxxxxxxxx", AInstEmit.Rev32_V, typeof(AOpCodeSimd));
SetA64("0x001110<<100000000010xxxxxxxxxx", AInstEmit.Rev64_V, typeof(AOpCodeSimd)); SetA64("0x001110<<100000000010xxxxxxxxxx", AInstEmit.Rev64_V, typeof(AOpCodeSimd));
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Rsubhn_V, typeof(AOpCodeSimdReg)); SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", AInstEmit.Rsubhn_V, typeof(AOpCodeSimdReg));
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg)); SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", AInstEmit.Saddw_V, typeof(AOpCodeSimdReg));

View file

@ -1,6 +1,7 @@
using ChocolArm64.Decoder; using ChocolArm64.Decoder;
using ChocolArm64.State; using ChocolArm64.State;
using ChocolArm64.Translation; using ChocolArm64.Translation;
using System;
using System.Reflection.Emit; using System.Reflection.Emit;
using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics.X86;
@ -144,7 +145,22 @@ namespace ChocolArm64.Instruction
EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or)); EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or));
} }
public static void Rev16_V(AILEmitterCtx Context)
{
EmitRev_V(Context, ContainerSize: 1);
}
public static void Rev32_V(AILEmitterCtx Context)
{
EmitRev_V(Context, ContainerSize: 2);
}
public static void Rev64_V(AILEmitterCtx Context) public static void Rev64_V(AILEmitterCtx Context)
{
EmitRev_V(Context, ContainerSize: 3);
}
private static void EmitRev_V(AILEmitterCtx Context, int ContainerSize)
{ {
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
@ -152,15 +168,25 @@ namespace ChocolArm64.Instruction
int Elems = Bytes >> Op.Size; int Elems = Bytes >> Op.Size;
int RevIndex = Elems - 1; if (Op.Size >= ContainerSize)
{
throw new InvalidOperationException();
}
int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1;
for (int Index = 0; Index < (Bytes >> Op.Size); Index++) for (int Index = 0; Index < (Bytes >> Op.Size); Index++)
{ {
EmitVectorExtractZx(Context, Op.Rn, RevIndex--, Op.Size); int RevIndex = Index ^ ContainerMask;
EmitVectorInsert(Context, Op.Rd, Index, Op.Size); EmitVectorExtractZx(Context, Op.Rn, RevIndex, Op.Size);
EmitVectorInsertTmp(Context, Index, Op.Size);
} }
Context.EmitLdvectmp();
Context.EmitStvec(Op.Rd);
if (Op.RegisterSize == ARegisterSize.SIMD64) if (Op.RegisterSize == ARegisterSize.SIMD64)
{ {
EmitVectorZeroUpper(Context, Op.Rd); EmitVectorZeroUpper(Context, Op.Rd);