Skip to content

Commit 1a63729

Browse files
Add Arm64 movemask
1 parent 6b5392b commit 1a63729

1 file changed

Lines changed: 21 additions & 1 deletion

File tree

src/ImageSharp/Common/Helpers/Vector128Utilities.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1319,9 +1319,29 @@ public static int MoveMask(Vector128<byte> value)
13191319
return Sse2.MoveMask(value);
13201320
}
13211321

1322+
// AdvSimd versions ported from Stack Overflow answer:
1323+
// https://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon
1324+
if (AdvSimd.Arm64.IsSupported)
1325+
{
1326+
// Shift values to align each MSB to its corresponding bit in the output
1327+
Vector128<sbyte> shift = Vector128.Create(-7, -6, -5, -4, -3, -2, -1, 0, -7, -6, -5, -4, -3, -2, -1, 0);
1328+
1329+
// Mask to isolate MSBs
1330+
Vector128<byte> msbMask = Vector128.Create((byte)0x80);
1331+
Vector128<byte> masked = value & msbMask;
1332+
1333+
// Shift each MSB into the correct bit position
1334+
Vector128<byte> shifted = AdvSimd.ShiftLogical(masked.AsSByte(), shift).AsByte();
1335+
1336+
// Sum lanes: lower 8 go into bits 0–7, upper 8 go into bits 8–15
1337+
byte lo = AdvSimd.Arm64.AddAcross(shifted.GetLower()).ToScalar();
1338+
byte hi = AdvSimd.Arm64.AddAcross(shifted.GetUpper()).ToScalar();
1339+
1340+
return lo + (hi << 8);
1341+
}
1342+
13221343
if (AdvSimd.IsSupported)
13231344
{
1324-
// https://stackoverflow.com/questions/11870910/sse-mm-movemask-epi8-equivalent-method-for-arm-neon
13251345
Vector128<byte> powers = Vector128.Create(1, 2, 4, 8, 16, 32, 64, 128, 1, 2, 4, 8, 16, 32, 64, 128);
13261346
Vector128<byte> msbMask = Vector128.Create((byte)0x80);
13271347
Vector128<byte> normalized = AdvSimd.CompareEqual(value & msbMask, msbMask); // 0xFF or 0x00

0 commit comments

Comments
 (0)