diff options
Diffstat (limited to 'ARMeilleure/State/NativeContext.cs')
-rw-r--r-- | ARMeilleure/State/NativeContext.cs | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/ARMeilleure/State/NativeContext.cs b/ARMeilleure/State/NativeContext.cs new file mode 100644 index 00000000..4e6a5302 --- /dev/null +++ b/ARMeilleure/State/NativeContext.cs @@ -0,0 +1,157 @@ +using ARMeilleure.IntermediateRepresentation; +using ARMeilleure.Memory; +using System; +using System.Runtime.InteropServices; + +namespace ARMeilleure.State +{ + class NativeContext : IDisposable + { + private const int IntSize = 8; + private const int VecSize = 16; + private const int FlagSize = 4; + private const int ExtraSize = 4; + + private const int TotalSize = RegisterConsts.IntRegsCount * IntSize + + RegisterConsts.VecRegsCount * VecSize + + RegisterConsts.FlagsCount * FlagSize + ExtraSize; + + public IntPtr BasePtr { get; } + + public NativeContext() + { + BasePtr = MemoryManagement.Allocate(TotalSize); + } + + public ulong GetX(int index) + { + if ((uint)index >= RegisterConsts.IntRegsCount) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return (ulong)Marshal.ReadInt64(BasePtr, index * IntSize); + } + + public void SetX(int index, ulong value) + { + if ((uint)index >= RegisterConsts.IntRegsCount) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + Marshal.WriteInt64(BasePtr, index * IntSize, (long)value); + } + + public V128 GetV(int index) + { + if ((uint)index >= RegisterConsts.IntRegsCount) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + int offset = RegisterConsts.IntRegsCount * IntSize + index * VecSize; + + return new V128( + Marshal.ReadInt64(BasePtr, offset + 0), + Marshal.ReadInt64(BasePtr, offset + 8)); + } + + public void SetV(int index, V128 value) + { + if ((uint)index >= RegisterConsts.IntRegsCount) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + int offset = RegisterConsts.IntRegsCount * IntSize + index * VecSize; + + Marshal.WriteInt64(BasePtr, offset + 0, value.GetInt64(0)); + Marshal.WriteInt64(BasePtr, offset + 8, value.GetInt64(1)); + } + + public bool GetPstateFlag(PState flag) + { + if ((uint)flag >= RegisterConsts.FlagsCount) + { + throw new ArgumentException($"Invalid flag \"{flag}\" specified."); + } + + int offset = + RegisterConsts.IntRegsCount * IntSize + + RegisterConsts.VecRegsCount * VecSize + (int)flag * FlagSize; + + int value = Marshal.ReadInt32(BasePtr, offset); + + return value != 0; + } + + public void SetPstateFlag(PState flag, bool value) + { + if ((uint)flag >= RegisterConsts.FlagsCount) + { + throw new ArgumentException($"Invalid flag \"{flag}\" specified."); + } + + int offset = + RegisterConsts.IntRegsCount * IntSize + + RegisterConsts.VecRegsCount * VecSize + (int)flag * FlagSize; + + Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0); + } + + public int GetCounter() + { + return Marshal.ReadInt32(BasePtr, GetCounterOffset()); + } + + public void SetCounter(int value) + { + Marshal.WriteInt32(BasePtr, GetCounterOffset(), value); + } + + public static int GetRegisterOffset(Register reg) + { + int offset, size; + + if (reg.Type == RegisterType.Integer) + { + offset = reg.Index * IntSize; + + size = IntSize; + } + else if (reg.Type == RegisterType.Vector) + { + offset = RegisterConsts.IntRegsCount * IntSize + reg.Index * VecSize; + + size = VecSize; + } + else /* if (reg.Type == RegisterType.Flag) */ + { + offset = RegisterConsts.IntRegsCount * IntSize + + RegisterConsts.VecRegsCount * VecSize + reg.Index * FlagSize; + + size = FlagSize; + } + + if ((uint)(offset + size) > (uint)TotalSize) + { + throw new ArgumentException("Invalid register."); + } + + return offset; + } + + public static int GetCounterOffset() + { + return RegisterConsts.IntRegsCount * IntSize + + RegisterConsts.VecRegsCount * VecSize + + RegisterConsts.FlagsCount * FlagSize; + } + + public void Dispose() + { + MemoryManagement.Free(BasePtr); + } + } +}
\ No newline at end of file |