using System.Diagnostics; namespace Unity.Burst.Intrinsics { public unsafe static partial class X86 { /// /// bmi1 intrinsics /// public static class Bmi1 { /// /// Evaluates to true at compile time if bmi1 intrinsics are supported. /// /// Burst ties bmi1 support to AVX2 support to simplify feature sets to support. /// public static bool IsBmi1Supported { get { return Avx2.IsAvx2Supported; } } /// /// Compute the bitwise NOT of 32-bit integer a and then AND with b, and store the results in dst. /// /// /// **** andn r32, r32, r32 /// /// 32-bit integer /// 32-bit integer /// 32-bit integer [DebuggerStepThrough] public static uint andn_u32(uint a, uint b) { return ~a & b; } /// /// Compute the bitwise NOT of 64-bit integer a and then AND with b, and store the results in dst. /// /// /// **** andn r64, r64, r64 /// /// 64-bit integer /// 64-bit integer /// 64-bit integer [DebuggerStepThrough] public static ulong andn_u64(ulong a, ulong b) { return ~a & b; } /// /// Extract contiguous bits from unsigned 32-bit integer a, and store the result in dst. Extract the number of bits specified by len, starting at the bit specified by start. /// /// /// **** bextr r32, r32, r32 /// /// 32-bit integer /// Starting bit /// Number of bits /// 32-bit integer [DebuggerStepThrough] public static uint bextr_u32(uint a, uint start, uint len) { start &= 0xff; if (start >= (sizeof(uint) * 8)) { return 0; } var aShifted = a >> (int)start; len &= 0xff; if (len >= (sizeof(uint) * 8)) { return aShifted; } return aShifted & ((1u << (int)len) - 1u); } /// /// Extract contiguous bits from unsigned 64-bit integer a, and store the result in dst. Extract the number of bits specified by len, starting at the bit specified by start. /// /// /// **** bextr r64, r64, r64 /// /// 64-bit integer /// Starting bit /// Number of bits /// 64-bit integer [DebuggerStepThrough] public static ulong bextr_u64(ulong a, uint start, uint len) { start &= 0xff; if (start >= (sizeof(ulong) * 8)) { return 0; } var aShifted = a >> (int)start; len &= 0xff; if (len >= (sizeof(ulong) * 8)) { return aShifted; } return aShifted & (((1ul) << (int)len) - 1u); } /// /// Extract contiguous bits from unsigned 32-bit integer a, and store the result in dst. Extract the number of bits specified by bits 15:8 of control, starting at the bit specified by bits 0:7 of control.. /// /// /// **** bextr r32, r32, r32 /// /// 32-bit integer /// Control /// 32-bit integer [DebuggerStepThrough] public static uint bextr2_u32(uint a, uint control) { uint start = control & byte.MaxValue; uint len = (control >> 8) & byte.MaxValue; return bextr_u32(a, start, len); } /// /// Extract contiguous bits from unsigned 64-bit integer a, and store the result in dst. Extract the number of bits specified by bits 15:8 of control, starting at the bit specified by bits 0:7 of control.. /// /// /// **** bextr r64, r64, r64 /// /// 32-bit integer /// Control /// 64-bit integer [DebuggerStepThrough] public static ulong bextr2_u64(ulong a, ulong control) { uint start = (uint)(control & byte.MaxValue); uint len = (uint)((control >> 8) & byte.MaxValue); return bextr_u64(a, start, len); } /// /// Extract the lowest set bit from unsigned 32-bit integer a and set the corresponding bit in dst. All other bits in dst are zeroed, and all bits are zeroed if no bits are set in a. /// /// /// **** blsi r32, r32 /// /// 32-bit integer /// 32-bit integer [DebuggerStepThrough] public static uint blsi_u32(uint a) { return (uint)(-(int)a) & a; } /// /// Extract the lowest set bit from unsigned 64-bit integer a and set the corresponding bit in dst. All other bits in dst are zeroed, and all bits are zeroed if no bits are set in a. /// /// /// **** blsi r64, r64 /// /// 64-bit integer /// 64-bit integer [DebuggerStepThrough] public static ulong blsi_u64(ulong a) { return (ulong)(-(long)a) & a; } /// /// Set all the lower bits of dst up to and including the lowest set bit in unsigned 32-bit integer a. /// /// /// **** blsmsk r32, r32 /// /// 32-bit integer /// 32-bit integer [DebuggerStepThrough] public static uint blsmsk_u32(uint a) { return (a - 1) ^ a; } /// /// Set all the lower bits of dst up to and including the lowest set bit in unsigned 64-bit integer a. /// /// /// **** blsmsk r64, r64 /// /// 64-bit integer /// 64-bit integer [DebuggerStepThrough] public static ulong blsmsk_u64(ulong a) { return (a - 1) ^ a; } /// /// Copy all bits from unsigned 32-bit integer a to dst, and reset (set to 0) the bit in dst that corresponds to the lowest set bit in a. /// /// /// **** blsr r32, r32 /// /// 32-bit integer /// 32-bit integer [DebuggerStepThrough] public static uint blsr_u32(uint a) { return (a - 1) & a; } /// /// Copy all bits from unsigned 64-bit integer a to dst, and reset (set to 0) the bit in dst that corresponds to the lowest set bit in a. /// /// /// **** blsr r64, r64 /// /// 64-bit integer /// 64-bit integer [DebuggerStepThrough] public static ulong blsr_u64(ulong a) { return (a - 1) & a; } /// /// Count the number of trailing zero bits in unsigned 32-bit integer a, and return that count in dst. /// /// /// **** tzcnt r32, r32 /// /// 32-bit integer /// 32-bit integer [DebuggerStepThrough] public static uint tzcnt_u32(uint a) { uint c = 32; a &= (uint)-(int)(a); if (a != 0) c--; if ((a & 0x0000FFFF) != 0) c -= 16; if ((a & 0x00FF00FF) != 0) c -= 8; if ((a & 0x0F0F0F0F) != 0) c -= 4; if ((a & 0x33333333) != 0) c -= 2; if ((a & 0x55555555) != 0) c -= 1; return c; } /// /// Count the number of trailing zero bits in unsigned 64-bit integer a, and return that count in dst. /// /// /// **** tzcnt r64, r64 /// /// 64-bit integer /// 64-bit integer [DebuggerStepThrough] public static ulong tzcnt_u64(ulong a) { ulong c = 64; a &= (ulong)-(long)(a); if (a != 0) c--; if ((a & 0x00000000FFFFFFFF) != 0) c -= 32; if ((a & 0x0000FFFF0000FFFF) != 0) c -= 16; if ((a & 0x00FF00FF00FF00FF) != 0) c -= 8; if ((a & 0x0F0F0F0F0F0F0F0F) != 0) c -= 4; if ((a & 0x3333333333333333) != 0) c -= 2; if ((a & 0x5555555555555555) != 0) c -= 1; return c; } } } }