CodeGenCommon.cs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using ARMeilleure.IntermediateRepresentation;
  2. using System.Numerics;
  3. namespace ARMeilleure.CodeGen.Arm64
  4. {
  5. static class CodeGenCommon
  6. {
  7. public const int TcAddressRegister = 8;
  8. public const int ReservedRegister = 17;
  9. public static bool ConstFitsOnSImm7(int value, int scale)
  10. {
  11. return (((value >> scale) << 25) >> (25 - scale)) == value;
  12. }
  13. public static bool ConstFitsOnSImm9(int value)
  14. {
  15. return ((value << 23) >> 23) == value;
  16. }
  17. public static bool ConstFitsOnUImm12(int value)
  18. {
  19. return (value & 0xfff) == value;
  20. }
  21. public static bool ConstFitsOnUImm12(int value, OperandType type)
  22. {
  23. int scale = Assembler.GetScaleForType(type);
  24. return (((value >> scale) & 0xfff) << scale) == value;
  25. }
  26. public static bool TryEncodeBitMask(Operand operand, out int immN, out int immS, out int immR)
  27. {
  28. return TryEncodeBitMask(operand.Type, operand.Value, out immN, out immS, out immR);
  29. }
  30. public static bool TryEncodeBitMask(OperandType type, ulong value, out int immN, out int immS, out int immR)
  31. {
  32. if (type == OperandType.I32)
  33. {
  34. value |= value << 32;
  35. }
  36. return TryEncodeBitMask(value, out immN, out immS, out immR);
  37. }
  38. public static bool TryEncodeBitMask(ulong value, out int immN, out int immS, out int immR)
  39. {
  40. // Some special values also can't be encoded:
  41. // 0 can't be encoded because we need to subtract 1 from onesCount (which would became negative if 0).
  42. // A value with all bits set can't be encoded because it is reserved according to the spec, because:
  43. // Any value AND all ones will be equal itself, so it's effectively a no-op.
  44. // Any value OR all ones will be equal all ones, so one can just use MOV.
  45. // Any value XOR all ones will be equal its inverse, so one can just use MVN.
  46. if (value == 0 || value == ulong.MaxValue)
  47. {
  48. immN = 0;
  49. immS = 0;
  50. immR = 0;
  51. return false;
  52. }
  53. // Normalize value, rotating it such that the LSB is 1: Ensures we get a complete element that has not
  54. // been cut-in-half across the word boundary.
  55. int rotation = BitOperations.TrailingZeroCount(value & (value + 1));
  56. ulong rotatedValue = ulong.RotateRight(value, rotation);
  57. // Now that we have a complete element in the LSB with the LSB = 1, determine size and number of ones
  58. // in element.
  59. int elementSize = BitOperations.TrailingZeroCount(rotatedValue & (rotatedValue + 1));
  60. int onesInElement = BitOperations.TrailingZeroCount(~rotatedValue);
  61. // Check the value is repeating; also ensures element size is a power of two.
  62. if (ulong.RotateRight(value, elementSize) != value)
  63. {
  64. immN = 0;
  65. immS = 0;
  66. immR = 0;
  67. return false;
  68. }
  69. immN = (elementSize >> 6) & 1;
  70. immS = (((~elementSize + 1) << 1) | (onesInElement - 1)) & 0x3f;
  71. immR = (elementSize - rotation) & (elementSize - 1);
  72. return true;
  73. }
  74. }
  75. }