using StgSharp.Math; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using static StgSharp.Optimization.CpuInfo; namespace StgSharp.Optimization { public static unsafe partial class SSE { public static m128 sqrtssM128Cache = new m128(); public static m128* sqrtssM128CachePointer; private static IntPtr sqrtssCodePointer; private static sqrtssDelegate sqrtssDele; private static byte[] sqrtssCodeBytes = new byte[] { 0x48,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // mov rax, [pointer location] 0x48,0x8b,0x00, // mov rax, [rax] 0xf3,0x0f,0x6f,0x00, // movqdu xmm0,xmmword ptr [rax] 0xf3,0x0f,0x51,0xc0, // sqrtss xmm0,xmm0 0xf3,0x0f,0x7f,0x00 // movdqu xmmword ptr [rax],xmm0 }; [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr VirtualAlloc( IntPtr lpAddress, UIntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect ); [DllImport("kernel32")] private static extern bool VirtualFree( IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType ); [Flags()] protected enum AllocationType : uint { COMMIT = 0x1000, RESERVE = 0x2000, RESET = 0x80000, LARGE_PAGES = 0x20000000, PHYSICAL = 0x400000, TOP_DOWN = 0x100000, WRITE_WATCH = 0x200000 } [Flags()] protected enum MemoryProtection : uint { EXECUTE = 0x10, EXECUTE_READ = 0x20, EXECUTE_READWRITE = 0x40, EXECUTE_WRITECOPY = 0x80, NOACCESS = 0x01, READONLY = 0x02, READWRITE = 0x04, WRITECOPY = 0x08, GUARD_Modifierflag = 0x100, NOCACHE_Modifierflag = 0x200, WRITECOMBINE_Modifierflag = 0x400 } private unsafe static void InitSqrtss() { byte[] sqrtssM128PointerBytes = BitConverter.GetBytes((ulong)sqrtssM128CachePointer); for (int i = 0; i < sqrtssM128PointerBytes.Length; i++) { sqrtssCodeBytes[2+i] = sqrtssCodeBytes[7-i]; } if (IntPtr.Size!=8) { throw new Exception("This SSE class support 64bits OS only presently!"); } sqrtssCodePointer = VirtualAlloc( IntPtr.Zero, new UIntPtr((uint)sqrtssCodeBytes.Length), AllocationType.COMMIT | AllocationType.RESERVE, MemoryProtection.EXECUTE_READWRITE ); Marshal.Copy(sqrtssCodeBytes, 0, sqrtssCodePointer, sqrtssCodeBytes.Length); sqrtssDele = (sqrtssDelegate)Marshal.GetDelegateForFunctionPointer(sqrtssCodePointer,typeof(sqrtssDelegate)); } public static float Sqrtss(float a) { fixed (m128* p = &sqrtssM128Cache) { sqrtssM128Cache.float0 = a; sqrtssDele(sqrtssM128Cache); return sqrtssM128Cache.float0; } } } [UnmanagedFunctionPointerAttribute(CallingConvention.ThisCall)] internal delegate void sqrtssDelegate(m128 a); }