NativeContext.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using ARMeilleure.IntermediateRepresentation;
  2. using ARMeilleure.Memory;
  3. using System;
  4. using System.Runtime.InteropServices;
  5. namespace ARMeilleure.State
  6. {
  7. class NativeContext : IDisposable
  8. {
  9. private const int IntSize = 8;
  10. private const int VecSize = 16;
  11. private const int FlagSize = 4;
  12. private const int ExtraSize = 4;
  13. private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
  14. RegisterConsts.VecRegsCount * VecSize +
  15. RegisterConsts.FlagsCount * FlagSize + ExtraSize;
  16. public IntPtr BasePtr { get; }
  17. public NativeContext()
  18. {
  19. BasePtr = MemoryManagement.Allocate(TotalSize);
  20. }
  21. public ulong GetX(int index)
  22. {
  23. if ((uint)index >= RegisterConsts.IntRegsCount)
  24. {
  25. throw new ArgumentOutOfRangeException(nameof(index));
  26. }
  27. return (ulong)Marshal.ReadInt64(BasePtr, index * IntSize);
  28. }
  29. public void SetX(int index, ulong value)
  30. {
  31. if ((uint)index >= RegisterConsts.IntRegsCount)
  32. {
  33. throw new ArgumentOutOfRangeException(nameof(index));
  34. }
  35. Marshal.WriteInt64(BasePtr, index * IntSize, (long)value);
  36. }
  37. public V128 GetV(int index)
  38. {
  39. if ((uint)index >= RegisterConsts.IntRegsCount)
  40. {
  41. throw new ArgumentOutOfRangeException(nameof(index));
  42. }
  43. int offset = RegisterConsts.IntRegsCount * IntSize + index * VecSize;
  44. return new V128(
  45. Marshal.ReadInt64(BasePtr, offset + 0),
  46. Marshal.ReadInt64(BasePtr, offset + 8));
  47. }
  48. public void SetV(int index, V128 value)
  49. {
  50. if ((uint)index >= RegisterConsts.IntRegsCount)
  51. {
  52. throw new ArgumentOutOfRangeException(nameof(index));
  53. }
  54. int offset = RegisterConsts.IntRegsCount * IntSize + index * VecSize;
  55. Marshal.WriteInt64(BasePtr, offset + 0, value.GetInt64(0));
  56. Marshal.WriteInt64(BasePtr, offset + 8, value.GetInt64(1));
  57. }
  58. public bool GetPstateFlag(PState flag)
  59. {
  60. if ((uint)flag >= RegisterConsts.FlagsCount)
  61. {
  62. throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
  63. }
  64. int offset =
  65. RegisterConsts.IntRegsCount * IntSize +
  66. RegisterConsts.VecRegsCount * VecSize + (int)flag * FlagSize;
  67. int value = Marshal.ReadInt32(BasePtr, offset);
  68. return value != 0;
  69. }
  70. public void SetPstateFlag(PState flag, bool value)
  71. {
  72. if ((uint)flag >= RegisterConsts.FlagsCount)
  73. {
  74. throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
  75. }
  76. int offset =
  77. RegisterConsts.IntRegsCount * IntSize +
  78. RegisterConsts.VecRegsCount * VecSize + (int)flag * FlagSize;
  79. Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0);
  80. }
  81. public int GetCounter()
  82. {
  83. return Marshal.ReadInt32(BasePtr, GetCounterOffset());
  84. }
  85. public void SetCounter(int value)
  86. {
  87. Marshal.WriteInt32(BasePtr, GetCounterOffset(), value);
  88. }
  89. public static int GetRegisterOffset(Register reg)
  90. {
  91. int offset, size;
  92. if (reg.Type == RegisterType.Integer)
  93. {
  94. offset = reg.Index * IntSize;
  95. size = IntSize;
  96. }
  97. else if (reg.Type == RegisterType.Vector)
  98. {
  99. offset = RegisterConsts.IntRegsCount * IntSize + reg.Index * VecSize;
  100. size = VecSize;
  101. }
  102. else /* if (reg.Type == RegisterType.Flag) */
  103. {
  104. offset = RegisterConsts.IntRegsCount * IntSize +
  105. RegisterConsts.VecRegsCount * VecSize + reg.Index * FlagSize;
  106. size = FlagSize;
  107. }
  108. if ((uint)(offset + size) > (uint)TotalSize)
  109. {
  110. throw new ArgumentException("Invalid register.");
  111. }
  112. return offset;
  113. }
  114. public static int GetCounterOffset()
  115. {
  116. return RegisterConsts.IntRegsCount * IntSize +
  117. RegisterConsts.VecRegsCount * VecSize +
  118. RegisterConsts.FlagsCount * FlagSize;
  119. }
  120. public void Dispose()
  121. {
  122. MemoryManagement.Free(BasePtr);
  123. }
  124. }
  125. }