No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Bmi1.cs 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using System.Diagnostics;
  2. namespace Unity.Burst.Intrinsics
  3. {
  4. public unsafe static partial class X86
  5. {
  6. /// <summary>
  7. /// bmi1 intrinsics
  8. /// </summary>
  9. public static class Bmi1
  10. {
  11. /// <summary>
  12. /// Evaluates to true at compile time if bmi1 intrinsics are supported.
  13. ///
  14. /// Burst ties bmi1 support to AVX2 support to simplify feature sets to support.
  15. /// </summary>
  16. public static bool IsBmi1Supported { get { return Avx2.IsAvx2Supported; } }
  17. /// <summary>
  18. /// Compute the bitwise NOT of 32-bit integer a and then AND with b, and store the results in dst.
  19. /// </summary>
  20. /// <remarks>
  21. /// **** andn r32, r32, r32
  22. /// </remarks>
  23. /// <param name="a">32-bit integer</param>
  24. /// <param name="b">32-bit integer</param>
  25. /// <returns>32-bit integer</returns>
  26. [DebuggerStepThrough]
  27. public static uint andn_u32(uint a, uint b)
  28. {
  29. return ~a & b;
  30. }
  31. /// <summary>
  32. /// Compute the bitwise NOT of 64-bit integer a and then AND with b, and store the results in dst.
  33. /// </summary>
  34. /// <remarks>
  35. /// **** andn r64, r64, r64
  36. /// </remarks>
  37. /// <param name="a">64-bit integer</param>
  38. /// <param name="b">64-bit integer</param>
  39. /// <returns>64-bit integer</returns>
  40. [DebuggerStepThrough]
  41. public static ulong andn_u64(ulong a, ulong b)
  42. {
  43. return ~a & b;
  44. }
  45. /// <summary>
  46. /// 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.
  47. /// </summary>
  48. /// <remarks>
  49. /// **** bextr r32, r32, r32
  50. /// </remarks>
  51. /// <param name="a">32-bit integer</param>
  52. /// <param name="start">Starting bit</param>
  53. /// <param name="len">Number of bits</param>
  54. /// <returns>32-bit integer</returns>
  55. [DebuggerStepThrough]
  56. public static uint bextr_u32(uint a, uint start, uint len)
  57. {
  58. start &= 0xff;
  59. if (start >= (sizeof(uint) * 8))
  60. {
  61. return 0;
  62. }
  63. var aShifted = a >> (int)start;
  64. len &= 0xff;
  65. if (len >= (sizeof(uint) * 8))
  66. {
  67. return aShifted;
  68. }
  69. return aShifted & ((1u << (int)len) - 1u);
  70. }
  71. /// <summary>
  72. /// 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.
  73. /// </summary>
  74. /// <remarks>
  75. /// **** bextr r64, r64, r64
  76. /// </remarks>
  77. /// <param name="a">64-bit integer</param>
  78. /// <param name="start">Starting bit</param>
  79. /// <param name="len">Number of bits</param>
  80. /// <returns>64-bit integer</returns>
  81. [DebuggerStepThrough]
  82. public static ulong bextr_u64(ulong a, uint start, uint len)
  83. {
  84. start &= 0xff;
  85. if (start >= (sizeof(ulong) * 8))
  86. {
  87. return 0;
  88. }
  89. var aShifted = a >> (int)start;
  90. len &= 0xff;
  91. if (len >= (sizeof(ulong) * 8))
  92. {
  93. return aShifted;
  94. }
  95. return aShifted & (((1ul) << (int)len) - 1u);
  96. }
  97. /// <summary>
  98. /// 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..
  99. /// </summary>
  100. /// <remarks>
  101. /// **** bextr r32, r32, r32
  102. /// </remarks>
  103. /// <param name="a">32-bit integer</param>
  104. /// <param name="control">Control</param>
  105. /// <returns>32-bit integer</returns>
  106. [DebuggerStepThrough]
  107. public static uint bextr2_u32(uint a, uint control)
  108. {
  109. uint start = control & byte.MaxValue;
  110. uint len = (control >> 8) & byte.MaxValue;
  111. return bextr_u32(a, start, len);
  112. }
  113. /// <summary>
  114. /// 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..
  115. /// </summary>
  116. /// <remarks>
  117. /// **** bextr r64, r64, r64
  118. /// </remarks>
  119. /// <param name="a">32-bit integer</param>
  120. /// <param name="control">Control</param>
  121. /// <returns>64-bit integer</returns>
  122. [DebuggerStepThrough]
  123. public static ulong bextr2_u64(ulong a, ulong control)
  124. {
  125. uint start = (uint)(control & byte.MaxValue);
  126. uint len = (uint)((control >> 8) & byte.MaxValue);
  127. return bextr_u64(a, start, len);
  128. }
  129. /// <summary>
  130. /// 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.
  131. /// </summary>
  132. /// <remarks>
  133. /// **** blsi r32, r32
  134. /// </remarks>
  135. /// <param name="a">32-bit integer</param>
  136. /// <returns>32-bit integer</returns>
  137. [DebuggerStepThrough]
  138. public static uint blsi_u32(uint a)
  139. {
  140. return (uint)(-(int)a) & a;
  141. }
  142. /// <summary>
  143. /// 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.
  144. /// </summary>
  145. /// <remarks>
  146. /// **** blsi r64, r64
  147. /// </remarks>
  148. /// <param name="a">64-bit integer</param>
  149. /// <returns>64-bit integer</returns>
  150. [DebuggerStepThrough]
  151. public static ulong blsi_u64(ulong a)
  152. {
  153. return (ulong)(-(long)a) & a;
  154. }
  155. /// <summary>
  156. /// Set all the lower bits of dst up to and including the lowest set bit in unsigned 32-bit integer a.
  157. /// </summary>
  158. /// <remarks>
  159. /// **** blsmsk r32, r32
  160. /// </remarks>
  161. /// <param name="a">32-bit integer</param>
  162. /// <returns>32-bit integer</returns>
  163. [DebuggerStepThrough]
  164. public static uint blsmsk_u32(uint a)
  165. {
  166. return (a - 1) ^ a;
  167. }
  168. /// <summary>
  169. /// Set all the lower bits of dst up to and including the lowest set bit in unsigned 64-bit integer a.
  170. /// </summary>
  171. /// <remarks>
  172. /// **** blsmsk r64, r64
  173. /// </remarks>
  174. /// <param name="a">64-bit integer</param>
  175. /// <returns>64-bit integer</returns>
  176. [DebuggerStepThrough]
  177. public static ulong blsmsk_u64(ulong a)
  178. {
  179. return (a - 1) ^ a;
  180. }
  181. /// <summary>
  182. /// 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.
  183. /// </summary>
  184. /// <remarks>
  185. /// **** blsr r32, r32
  186. /// </remarks>
  187. /// <param name="a">32-bit integer</param>
  188. /// <returns>32-bit integer</returns>
  189. [DebuggerStepThrough]
  190. public static uint blsr_u32(uint a)
  191. {
  192. return (a - 1) & a;
  193. }
  194. /// <summary>
  195. /// 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.
  196. /// </summary>
  197. /// <remarks>
  198. /// **** blsr r64, r64
  199. /// </remarks>
  200. /// <param name="a">64-bit integer</param>
  201. /// <returns>64-bit integer</returns>
  202. [DebuggerStepThrough]
  203. public static ulong blsr_u64(ulong a)
  204. {
  205. return (a - 1) & a;
  206. }
  207. /// <summary>
  208. /// Count the number of trailing zero bits in unsigned 32-bit integer a, and return that count in dst.
  209. /// </summary>
  210. /// <remarks>
  211. /// **** tzcnt r32, r32
  212. /// </remarks>
  213. /// <param name="a">32-bit integer</param>
  214. /// <returns>32-bit integer</returns>
  215. [DebuggerStepThrough]
  216. public static uint tzcnt_u32(uint a)
  217. {
  218. uint c = 32;
  219. a &= (uint)-(int)(a);
  220. if (a != 0) c--;
  221. if ((a & 0x0000FFFF) != 0) c -= 16;
  222. if ((a & 0x00FF00FF) != 0) c -= 8;
  223. if ((a & 0x0F0F0F0F) != 0) c -= 4;
  224. if ((a & 0x33333333) != 0) c -= 2;
  225. if ((a & 0x55555555) != 0) c -= 1;
  226. return c;
  227. }
  228. /// <summary>
  229. /// Count the number of trailing zero bits in unsigned 64-bit integer a, and return that count in dst.
  230. /// </summary>
  231. /// <remarks>
  232. /// **** tzcnt r64, r64
  233. /// </remarks>
  234. /// <param name="a">64-bit integer</param>
  235. /// <returns>64-bit integer</returns>
  236. [DebuggerStepThrough]
  237. public static ulong tzcnt_u64(ulong a)
  238. {
  239. ulong c = 64;
  240. a &= (ulong)-(long)(a);
  241. if (a != 0) c--;
  242. if ((a & 0x00000000FFFFFFFF) != 0) c -= 32;
  243. if ((a & 0x0000FFFF0000FFFF) != 0) c -= 16;
  244. if ((a & 0x00FF00FF00FF00FF) != 0) c -= 8;
  245. if ((a & 0x0F0F0F0F0F0F0F0F) != 0) c -= 4;
  246. if ((a & 0x3333333333333333) != 0) c -= 2;
  247. if ((a & 0x5555555555555555) != 0) c -= 1;
  248. return c;
  249. }
  250. }
  251. }
  252. }