| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- using ARMeilleure.State;
- using Ryujinx.Memory;
- using System;
- using System.Runtime.InteropServices;
- using System.Threading;
- namespace Ryujinx.Cpu.AppleHv
- {
- class HvExecutionContextVcpu : IHvExecutionContext
- {
- private static MemoryBlock _setSimdFpRegFuncMem;
- private delegate hv_result_t SetSimdFpReg(ulong vcpu, hv_simd_fp_reg_t reg, in V128 value, IntPtr funcPtr);
- private static SetSimdFpReg _setSimdFpReg;
- private static IntPtr _setSimdFpRegNativePtr;
- static HvExecutionContextVcpu()
- {
- // .NET does not support passing vectors by value, so we need to pass a pointer and use a native
- // function to load the value into a vector register.
- _setSimdFpRegFuncMem = new MemoryBlock(MemoryBlock.GetPageSize());
- _setSimdFpRegFuncMem.Write(0, 0x3DC00040u); // LDR Q0, [X2]
- _setSimdFpRegFuncMem.Write(4, 0xD61F0060u); // BR X3
- _setSimdFpRegFuncMem.Reprotect(0, _setSimdFpRegFuncMem.Size, MemoryPermission.ReadAndExecute);
- _setSimdFpReg = Marshal.GetDelegateForFunctionPointer<SetSimdFpReg>(_setSimdFpRegFuncMem.Pointer);
- if (NativeLibrary.TryLoad(HvApi.LibraryName, out IntPtr hvLibHandle))
- {
- _setSimdFpRegNativePtr = NativeLibrary.GetExport(hvLibHandle, nameof(HvApi.hv_vcpu_set_simd_fp_reg));
- }
- }
- public ulong Pc
- {
- get
- {
- HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_PC, out ulong pc).ThrowOnError();
- return pc;
- }
- set
- {
- HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_PC, value).ThrowOnError();
- }
- }
- public ulong ElrEl1
- {
- get
- {
- HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, out ulong elr).ThrowOnError();
- return elr;
- }
- set
- {
- HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ELR_EL1, value).ThrowOnError();
- }
- }
- public ulong EsrEl1
- {
- get
- {
- HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, out ulong esr).ThrowOnError();
- return esr;
- }
- set
- {
- HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_ESR_EL1, value).ThrowOnError();
- }
- }
- public long TpidrEl0
- {
- get
- {
- HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDR_EL0, out ulong tpidrEl0).ThrowOnError();
- return (long)tpidrEl0;
- }
- set
- {
- HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDR_EL0, (ulong)value).ThrowOnError();
- }
- }
- public long TpidrroEl0
- {
- get
- {
- HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDRRO_EL0, out ulong tpidrroEl0).ThrowOnError();
- return (long)tpidrroEl0;
- }
- set
- {
- HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_TPIDRRO_EL0, (ulong)value).ThrowOnError();
- }
- }
- public uint Pstate
- {
- get
- {
- HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_CPSR, out ulong cpsr).ThrowOnError();
- return (uint)cpsr;
- }
- set
- {
- HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_CPSR, (ulong)value).ThrowOnError();
- }
- }
- public uint Fpcr
- {
- get
- {
- HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_FPCR, out ulong fpcr).ThrowOnError();
- return (uint)fpcr;
- }
- set
- {
- HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_FPCR, (ulong)value).ThrowOnError();
- }
- }
- public uint Fpsr
- {
- get
- {
- HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_FPSR, out ulong fpsr).ThrowOnError();
- return (uint)fpsr;
- }
- set
- {
- HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_FPSR, (ulong)value).ThrowOnError();
- }
- }
- private ulong _vcpu;
- private int _interruptRequested;
- public HvExecutionContextVcpu(ulong vcpu)
- {
- _vcpu = vcpu;
- }
- public ulong GetX(int index)
- {
- if (index == 31)
- {
- HvApi.hv_vcpu_get_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_SP_EL0, out ulong value).ThrowOnError();
- return value;
- }
- else
- {
- HvApi.hv_vcpu_get_reg(_vcpu, hv_reg_t.HV_REG_X0 + (uint)index, out ulong value).ThrowOnError();
- return value;
- }
- }
- public void SetX(int index, ulong value)
- {
- if (index == 31)
- {
- HvApi.hv_vcpu_set_sys_reg(_vcpu, hv_sys_reg_t.HV_SYS_REG_SP_EL0, value).ThrowOnError();
- }
- else
- {
- HvApi.hv_vcpu_set_reg(_vcpu, hv_reg_t.HV_REG_X0 + (uint)index, value).ThrowOnError();
- }
- }
- public V128 GetV(int index)
- {
- HvApi.hv_vcpu_get_simd_fp_reg(_vcpu, hv_simd_fp_reg_t.HV_SIMD_FP_REG_Q0 + (uint)index, out hv_simd_fp_uchar16_t value).ThrowOnError();
- return new V128(value.Low, value.High);
- }
- public void SetV(int index, V128 value)
- {
- _setSimdFpReg(_vcpu, hv_simd_fp_reg_t.HV_SIMD_FP_REG_Q0 + (uint)index, value, _setSimdFpRegNativePtr).ThrowOnError();
- }
- public void RequestInterrupt()
- {
- if (Interlocked.Exchange(ref _interruptRequested, 1) == 0)
- {
- ulong vcpu = _vcpu;
- HvApi.hv_vcpus_exit(ref vcpu, 1);
- }
- }
- public bool GetAndClearInterruptRequested()
- {
- return Interlocked.Exchange(ref _interruptRequested, 0) != 0;
- }
- }
- }
|