| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using ARMeilleure.IntermediateRepresentation;
- using ARMeilleure.Memory;
- using System;
- using System.Runtime.CompilerServices;
- namespace ARMeilleure.State
- {
- class NativeContext : IDisposable
- {
- private unsafe struct NativeCtxStorage
- {
- public fixed ulong X[RegisterConsts.IntRegsCount];
- public fixed ulong V[RegisterConsts.VecRegsCount * 2];
- public fixed uint Flags[RegisterConsts.FlagsCount];
- public fixed uint FpFlags[RegisterConsts.FpFlagsCount];
- public int Counter;
- public ulong DispatchAddress;
- public ulong ExclusiveAddress;
- public ulong ExclusiveValueLow;
- public ulong ExclusiveValueHigh;
- public int Running;
- }
- private static NativeCtxStorage _dummyStorage = new NativeCtxStorage();
- private readonly IJitMemoryBlock _block;
- public IntPtr BasePtr => _block.Pointer;
- public NativeContext(IJitMemoryAllocator allocator)
- {
- _block = allocator.Allocate((ulong)Unsafe.SizeOf<NativeCtxStorage>());
- GetStorage().ExclusiveAddress = ulong.MaxValue;
- }
- public unsafe ulong GetX(int index)
- {
- if ((uint)index >= RegisterConsts.IntRegsCount)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- return GetStorage().X[index];
- }
- public unsafe void SetX(int index, ulong value)
- {
- if ((uint)index >= RegisterConsts.IntRegsCount)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- GetStorage().X[index] = value;
- }
- public unsafe V128 GetV(int index)
- {
- if ((uint)index >= RegisterConsts.VecRegsCount)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- return new V128(GetStorage().V[index * 2 + 0], GetStorage().V[index * 2 + 1]);
- }
- public unsafe void SetV(int index, V128 value)
- {
- if ((uint)index >= RegisterConsts.VecRegsCount)
- {
- throw new ArgumentOutOfRangeException(nameof(index));
- }
- GetStorage().V[index * 2 + 0] = value.Extract<ulong>(0);
- GetStorage().V[index * 2 + 1] = value.Extract<ulong>(1);
- }
- public unsafe bool GetPstateFlag(PState flag)
- {
- if ((uint)flag >= RegisterConsts.FlagsCount)
- {
- throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
- }
- return GetStorage().Flags[(int)flag] != 0;
- }
- public unsafe void SetPstateFlag(PState flag, bool value)
- {
- if ((uint)flag >= RegisterConsts.FlagsCount)
- {
- throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
- }
- GetStorage().Flags[(int)flag] = value ? 1u : 0u;
- }
- public unsafe bool GetFPStateFlag(FPState flag)
- {
- if ((uint)flag >= RegisterConsts.FpFlagsCount)
- {
- throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
- }
- return GetStorage().FpFlags[(int)flag] != 0;
- }
- public unsafe void SetFPStateFlag(FPState flag, bool value)
- {
- if ((uint)flag >= RegisterConsts.FpFlagsCount)
- {
- throw new ArgumentException($"Invalid flag \"{flag}\" specified.");
- }
- GetStorage().FpFlags[(int)flag] = value ? 1u : 0u;
- }
- public int GetCounter() => GetStorage().Counter;
- public void SetCounter(int value) => GetStorage().Counter = value;
- public bool GetRunning() => GetStorage().Running != 0;
- public void SetRunning(bool value) => GetStorage().Running = value ? 1 : 0;
- public unsafe static int GetRegisterOffset(Register reg)
- {
- if (reg.Type == RegisterType.Integer)
- {
- if ((uint)reg.Index >= RegisterConsts.IntRegsCount)
- {
- throw new ArgumentException("Invalid register.");
- }
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.X[reg.Index]);
- }
- else if (reg.Type == RegisterType.Vector)
- {
- if ((uint)reg.Index >= RegisterConsts.VecRegsCount)
- {
- throw new ArgumentException("Invalid register.");
- }
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.V[reg.Index * 2]);
- }
- else if (reg.Type == RegisterType.Flag)
- {
- if ((uint)reg.Index >= RegisterConsts.FlagsCount)
- {
- throw new ArgumentException("Invalid register.");
- }
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.Flags[reg.Index]);
- }
- else /* if (reg.Type == RegisterType.FpFlag) */
- {
- if ((uint)reg.Index >= RegisterConsts.FpFlagsCount)
- {
- throw new ArgumentException("Invalid register.");
- }
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.FpFlags[reg.Index]);
- }
- }
- public static int GetCounterOffset()
- {
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.Counter);
- }
- public static int GetDispatchAddressOffset()
- {
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.DispatchAddress);
- }
- public static int GetExclusiveAddressOffset()
- {
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.ExclusiveAddress);
- }
- public static int GetExclusiveValueOffset()
- {
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.ExclusiveValueLow);
- }
- public static int GetRunningOffset()
- {
- return StorageOffset(ref _dummyStorage, ref _dummyStorage.Running);
- }
- private static int StorageOffset<T>(ref NativeCtxStorage storage, ref T target)
- {
- return (int)Unsafe.ByteOffset(ref Unsafe.As<NativeCtxStorage, T>(ref storage), ref target);
- }
- private unsafe ref NativeCtxStorage GetStorage() => ref Unsafe.AsRef<NativeCtxStorage>((void*)_block.Pointer);
- public void Dispose() => _block.Dispose();
- }
- }
|