BitfieldExtensions.cs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. using System.Numerics;
  2. using System.Runtime.CompilerServices;
  3. namespace Ryujinx.Common.Utilities
  4. {
  5. public static class BitfieldExtensions
  6. {
  7. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  8. public static bool Extract<T>(this T value, int lsb) where T : IBinaryInteger<T>
  9. {
  10. int bitSize = Unsafe.SizeOf<T>() * 8;
  11. lsb &= bitSize - 1;
  12. return !T.IsZero((value >>> lsb) & T.One);
  13. }
  14. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  15. public static T Extract<T>(this T value, int lsb, int length) where T : IBinaryInteger<T>
  16. {
  17. int bitSize = Unsafe.SizeOf<T>() * 8;
  18. lsb &= bitSize - 1;
  19. return (value >>> lsb) & (~T.Zero >>> (bitSize - length));
  20. }
  21. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  22. public static T ExtractSx<T>(this T value, int lsb, int length) where T : IBinaryInteger<T>
  23. {
  24. int bitSize = Unsafe.SizeOf<T>() * 8;
  25. int shift = lsb & (bitSize - 1);
  26. return (value << (bitSize - (shift + length))) >> (bitSize - length);
  27. }
  28. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  29. public static T Insert<T>(this T value, int lsb, bool toInsert) where T : IBinaryInteger<T>
  30. {
  31. int bitSize = Unsafe.SizeOf<T>() * 8;
  32. lsb &= bitSize - 1;
  33. T mask = T.One << lsb;
  34. return (value & ~mask) | (toInsert ? mask : T.Zero);
  35. }
  36. [MethodImpl(MethodImplOptions.AggressiveInlining)]
  37. public static T Insert<T>(this T value, int lsb, int length, T toInsert) where T : IBinaryInteger<T>
  38. {
  39. int bitSize = Unsafe.SizeOf<T>() * 8;
  40. lsb &= bitSize - 1;
  41. T mask = (~T.Zero >>> (bitSize - length)) << lsb;
  42. return (value & ~mask) | ((toInsert << lsb) & mask);
  43. }
  44. }
  45. }