Add Rbit_V instruction. Add 8 tests (Rbit_V; Rev16_V, Rev32_V, Rev64_V). Improve CountSetBits8() algorithm. (#212)

* Update AOpCodeTable.cs

* Update AInstEmitSimdArithmetic.cs

* Update AInstEmitSimdLogical.cs

* Update AVectorHelper.cs

* Update ASoftFallback.cs

* Update Instructions.cs

* Update CpuTestSimd.cs

* Update CpuTestSimdReg.cs

* Improve CountSetBits8() algorithm.

* Improve CountSetBits8() algorithm.
This commit is contained in:
LDj3SNuD 2018-07-03 08:31:16 +02:00 committed by gdkchan
parent 051740f344
commit 8d7582a918
5 changed files with 55 additions and 21 deletions

View file

@ -348,6 +348,7 @@ 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("0x10111001100000010110xxxxxxxxxx", AInstEmit.Rbit_V, typeof(AOpCodeSimd));
SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd)); SetA64("0x00111000100000000110xxxxxxxxxx", AInstEmit.Rev16_V, typeof(AOpCodeSimd));
SetA64("0x1011100x100000000010xxxxxxxxxx", AInstEmit.Rev32_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));

View file

@ -151,9 +151,9 @@ namespace ChocolArm64.Instruction
{ {
EmitVectorExtractZx(Context, Op.Rn, Index, 0); EmitVectorExtractZx(Context, Op.Rn, Index, 0);
Context.Emit(OpCodes.Conv_U1); Context.Emit(OpCodes.Conv_U4);
AVectorHelper.EmitCall(Context, nameof(AVectorHelper.CountSetBits8)); ASoftFallback.EmitCall(Context, nameof(ASoftFallback.CountSetBits8));
Context.Emit(OpCodes.Conv_U8); Context.Emit(OpCodes.Conv_U8);

View file

@ -56,8 +56,9 @@ namespace ChocolArm64.Instruction
AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp; AOpCodeSimdReg Op = (AOpCodeSimdReg)Context.CurrOp;
int Bytes = Context.CurrOp.GetBitsCount() >> 3; int Bytes = Context.CurrOp.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.Rd, Index, Op.Size); EmitVectorExtractZx(Context, Op.Rd, Index, Op.Size);
EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size); EmitVectorExtractZx(Context, Op.Rn, Index, Op.Size);
@ -145,6 +146,31 @@ namespace ChocolArm64.Instruction
EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or)); EmitVectorImmBinaryOp(Context, () => Context.Emit(OpCodes.Or));
} }
public static void Rbit_V(AILEmitterCtx Context)
{
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
int Elems = Op.RegisterSize == ARegisterSize.SIMD128 ? 16 : 8;
for (int Index = 0; Index < Elems; Index++)
{
EmitVectorExtractZx(Context, Op.Rn, Index, 0);
Context.Emit(OpCodes.Conv_U4);
ASoftFallback.EmitCall(Context, nameof(ASoftFallback.ReverseBits8));
Context.Emit(OpCodes.Conv_U8);
EmitVectorInsert(Context, Op.Rd, Index, 0);
}
if (Op.RegisterSize == ARegisterSize.SIMD64)
{
EmitVectorZeroUpper(Context, Op.Rd);
}
}
public static void Rev16_V(AILEmitterCtx Context) public static void Rev16_V(AILEmitterCtx Context)
{ {
EmitRev_V(Context, ContainerSize: 1); EmitRev_V(Context, ContainerSize: 1);
@ -164,18 +190,17 @@ namespace ChocolArm64.Instruction
{ {
AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp; AOpCodeSimd Op = (AOpCodeSimd)Context.CurrOp;
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
int Elems = Bytes >> Op.Size;
if (Op.Size >= ContainerSize) if (Op.Size >= ContainerSize)
{ {
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
int Bytes = Context.CurrOp.GetBitsCount() >> 3;
int Elems = Bytes >> Op.Size;
int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1; int ContainerMask = (1 << (ContainerSize - Op.Size)) - 1;
for (int Index = 0; Index < (Bytes >> Op.Size); Index++) for (int Index = 0; Index < Elems; Index++)
{ {
int RevIndex = Index ^ ContainerMask; int RevIndex = Index ^ ContainerMask;

View file

@ -30,6 +30,14 @@ namespace ChocolArm64.Instruction
return (ulong)Size; return (ulong)Size;
} }
public static uint CountSetBits8(uint Value)
{
Value = ((Value >> 1) & 0x55) + (Value & 0x55);
Value = ((Value >> 2) & 0x33) + (Value & 0x33);
return (Value >> 4) + (Value & 0x0f);
}
private const uint Crc32RevPoly = 0xedb88320; private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78; private const uint Crc32cRevPoly = 0x82f63b78;
@ -89,6 +97,14 @@ namespace ChocolArm64.Instruction
return Crc; return Crc;
} }
public static uint ReverseBits8(uint Value)
{
Value = ((Value & 0xaa) >> 1) | ((Value & 0x55) << 1);
Value = ((Value & 0xcc) >> 2) | ((Value & 0x33) << 2);
return (Value >> 4) | ((Value & 0x0f) << 4);
}
public static uint ReverseBits32(uint Value) public static uint ReverseBits32(uint Value)
{ {
Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1); Value = ((Value & 0xaaaaaaaa) >> 1) | ((Value & 0x55555555) << 1);

View file

@ -93,14 +93,6 @@ namespace ChocolArm64.Instruction
Value < ulong.MinValue ? ulong.MinValue : (ulong)Value; Value < ulong.MinValue ? ulong.MinValue : (ulong)Value;
} }
public static int CountSetBits8(byte Value)
{
return ((Value >> 0) & 1) + ((Value >> 1) & 1) +
((Value >> 2) & 1) + ((Value >> 3) & 1) +
((Value >> 4) & 1) + ((Value >> 5) & 1) +
((Value >> 6) & 1) + (Value >> 7);
}
public static double Max(double LHS, double RHS) public static double Max(double LHS, double RHS)
{ {
if (LHS == 0.0 && RHS == 0.0) if (LHS == 0.0 && RHS == 0.0)