mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2025-06-28 23:50:46 -07:00
Implement VCNT instruction (#1963)
* Implement VCNT based on AArch64 CNT Add tests * Update PTC version * Address LDj's comments * Explicit size in encoding * Tighter tests * Replace SoftFallback with IR helper Co-authored-by: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> * Reduce one BitwiseAnd from IR fallback Based on popcount64b from https://en.wikipedia.org/wiki/Hamming_weight#Efficient_implementation * Rename parameter and add assert Co-authored-by: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> Co-authored-by: LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>
This commit is contained in:
@ -289,7 +289,7 @@ namespace ARMeilleure.Instructions
|
||||
}
|
||||
else
|
||||
{
|
||||
de = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountSetBits8)), ne);
|
||||
de = EmitCountSetBits8(context, ne);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, 0);
|
||||
|
@ -135,6 +135,34 @@ namespace ARMeilleure.Instructions
|
||||
EmitVectorBinaryWideOpI32(context, (op1, op2) => context.Add(op1, op2), !op.U);
|
||||
}
|
||||
|
||||
public static void Vcnt(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdCmpZ op = (OpCode32SimdCmpZ)context.CurrOp;
|
||||
|
||||
Operand res = GetVecA32(op.Qd);
|
||||
|
||||
int elems = op.GetBytesCount();
|
||||
|
||||
for (int index = 0; index < elems; index++)
|
||||
{
|
||||
Operand de;
|
||||
Operand me = EmitVectorExtractZx32(context, op.Qm, op.Im + index, op.Size);
|
||||
|
||||
if (Optimizations.UsePopCnt)
|
||||
{
|
||||
de = context.AddIntrinsicInt(Intrinsic.X86Popcnt, me);
|
||||
}
|
||||
else
|
||||
{
|
||||
de = EmitCountSetBits8(context, me);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, de, op.Id + index, op.Size);
|
||||
}
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
|
||||
public static void Vdup(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdDupGP op = (OpCode32SimdDupGP)context.CurrOp;
|
||||
|
@ -234,6 +234,18 @@ namespace ARMeilleure.Instructions
|
||||
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
||||
}
|
||||
|
||||
public static Operand EmitCountSetBits8(ArmEmitterContext context, Operand op) // "size" is 8 (SIMD&FP Inst.).
|
||||
{
|
||||
Debug.Assert(op.Type == OperandType.I32 || op.Type == OperandType.I64);
|
||||
|
||||
Operand op0 = context.Subtract(op, context.BitwiseAnd(context.ShiftRightUI(op, Const(1)), Const(op.Type, 0x55L)));
|
||||
|
||||
Operand c1 = Const(op.Type, 0x33L);
|
||||
Operand op1 = context.Add(context.BitwiseAnd(context.ShiftRightUI(op0, Const(2)), c1), context.BitwiseAnd(op0, c1));
|
||||
|
||||
return context.BitwiseAnd(context.Add(op1, context.ShiftRightUI(op1, Const(4))), Const(op.Type, 0x0fL));
|
||||
}
|
||||
|
||||
public static void EmitScalarUnaryOpF(ArmEmitterContext context, Intrinsic inst32, Intrinsic inst64)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
@ -567,6 +567,7 @@ namespace ARMeilleure.Instructions
|
||||
Vclt,
|
||||
Vcmp,
|
||||
Vcmpe,
|
||||
Vcnt,
|
||||
Vcvt,
|
||||
Vdiv,
|
||||
Vdup,
|
||||
|
@ -846,14 +846,6 @@ namespace ARMeilleure.Instructions
|
||||
|
||||
return (ulong)count;
|
||||
}
|
||||
|
||||
public static ulong CountSetBits8(ulong value) // "size" is 8 (SIMD&FP Inst.).
|
||||
{
|
||||
value = ((value >> 1) & 0x55ul) + (value & 0x55ul);
|
||||
value = ((value >> 2) & 0x33ul) + (value & 0x33ul);
|
||||
|
||||
return (value >> 4) + (value & 0x0ful);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region "Table"
|
||||
|
Reference in New Issue
Block a user