NativeContext.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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 = 8;
  13. private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
  14. RegisterConsts.VecRegsCount * VecSize +
  15. RegisterConsts.FlagsCount * FlagSize +
  16. RegisterConsts.FpFlagsCount * FlagSize + ExtraSize;
  17. private readonly IJitMemoryBlock _block;
  18. public IntPtr BasePtr => _block.Pointer;
  19. public NativeContext(IJitMemoryAllocator allocator)
  20. {
  21. _block = allocator.Allocate(TotalSize);
  22. }
  23. public ulong GetX(int index)
  24. {
  25. if ((uint)index >= RegisterConsts.IntRegsCount)
  26. {
  27. throw new ArgumentOutOfRangeException(nameof(index));
  28. }
  29. return (ulong)Marshal.ReadInt64(BasePtr, index * IntSize);
  30. }
  31. public void SetX(int index, ulong value)
  32. {
  33. if ((uint)index >= RegisterConsts.IntRegsCount)
  34. {
  35. throw new ArgumentOutOfRangeException(nameof(index));
  36. }
  37. Marshal.WriteInt64(BasePtr, index * IntSize, (long)value);
  38. }
  39. public V128 GetV(int index)
  40. {
  41. if ((uint)index >= RegisterConsts.IntRegsCount)
  42. {
  43. throw new ArgumentOutOfRangeException(nameof(index));
  44. }
  45. int offset = RegisterConsts.IntRegsCount * IntSize + index * VecSize;
  46. return new V128(
  47. Marshal.ReadInt64(BasePtr, offset + 0),
  48. Marshal.ReadInt64(BasePtr, offset + 8));
  49. }
  50. public void SetV(int index, V128 value)
  51. {
  52. if ((uint)index >= RegisterConsts.IntRegsCount)
  53. {
  54. throw new ArgumentOutOfRangeException(nameof(index));
  55. }
  56. int offset = RegisterConsts.IntRegsCount * IntSize + index * VecSize;
  57. Marshal.WriteInt64(BasePtr, offset + 0, value.Extract<long>(0));
  58. Marshal.WriteInt64(BasePtr, offset + 8, value.Extract<long>(1));
  59. }
  60. public bool GetPstateFlag(PState flag)
  61. {
  62. if ((uint)flag >= RegisterConsts.FlagsCount)
  63. {
  64. throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
  65. }
  66. int offset =
  67. RegisterConsts.IntRegsCount * IntSize +
  68. RegisterConsts.VecRegsCount * VecSize + (int)flag * FlagSize;
  69. int value = Marshal.ReadInt32(BasePtr, offset);
  70. return value != 0;
  71. }
  72. public void SetPstateFlag(PState flag, bool value)
  73. {
  74. if ((uint)flag >= RegisterConsts.FlagsCount)
  75. {
  76. throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
  77. }
  78. int offset =
  79. RegisterConsts.IntRegsCount * IntSize +
  80. RegisterConsts.VecRegsCount * VecSize + (int)flag * FlagSize;
  81. Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0);
  82. }
  83. public bool GetFPStateFlag(FPState flag)
  84. {
  85. if ((uint)flag >= RegisterConsts.FlagsCount)
  86. {
  87. throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
  88. }
  89. int offset =
  90. RegisterConsts.IntRegsCount * IntSize +
  91. RegisterConsts.VecRegsCount * VecSize +
  92. RegisterConsts.FlagsCount * FlagSize + (int)flag * FlagSize;
  93. int value = Marshal.ReadInt32(BasePtr, offset);
  94. return value != 0;
  95. }
  96. public void SetFPStateFlag(FPState flag, bool value)
  97. {
  98. if ((uint)flag >= RegisterConsts.FlagsCount)
  99. {
  100. throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
  101. }
  102. int offset =
  103. RegisterConsts.IntRegsCount * IntSize +
  104. RegisterConsts.VecRegsCount * VecSize +
  105. RegisterConsts.FlagsCount * FlagSize + (int)flag * FlagSize;
  106. Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0);
  107. }
  108. public int GetCounter()
  109. {
  110. return Marshal.ReadInt32(BasePtr, GetCounterOffset());
  111. }
  112. public void SetCounter(int value)
  113. {
  114. Marshal.WriteInt32(BasePtr, GetCounterOffset(), value);
  115. }
  116. public static int GetRegisterOffset(Register reg)
  117. {
  118. int offset, size;
  119. if (reg.Type == RegisterType.Integer)
  120. {
  121. offset = reg.Index * IntSize;
  122. size = IntSize;
  123. }
  124. else if (reg.Type == RegisterType.Vector)
  125. {
  126. offset = RegisterConsts.IntRegsCount * IntSize + reg.Index * VecSize;
  127. size = VecSize;
  128. }
  129. else /* if (reg.Type == RegisterType.Flag) */
  130. {
  131. offset = RegisterConsts.IntRegsCount * IntSize +
  132. RegisterConsts.VecRegsCount * VecSize + reg.Index * FlagSize;
  133. size = FlagSize;
  134. }
  135. if ((uint)(offset + size) > (uint)TotalSize)
  136. {
  137. throw new ArgumentException("Invalid register.");
  138. }
  139. return offset;
  140. }
  141. public static int GetCounterOffset()
  142. {
  143. return RegisterConsts.IntRegsCount * IntSize +
  144. RegisterConsts.VecRegsCount * VecSize +
  145. RegisterConsts.FlagsCount * FlagSize +
  146. RegisterConsts.FpFlagsCount * FlagSize;
  147. }
  148. public static int GetCallAddressOffset()
  149. {
  150. return RegisterConsts.IntRegsCount * IntSize +
  151. RegisterConsts.VecRegsCount * VecSize +
  152. RegisterConsts.FlagsCount * FlagSize +
  153. RegisterConsts.FpFlagsCount * FlagSize + 4;
  154. }
  155. public void Dispose()
  156. {
  157. _block.Dispose();
  158. }
  159. }
  160. }