mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-29 20:30:44 +00:00
281 lines
8.1 KiB
C#
281 lines
8.1 KiB
C#
using Cosmos.Assembler;
|
|
using Cosmos.Assembler.x86;
|
|
using Cosmos.IL2CPU.Plugs;
|
|
|
|
using System;
|
|
|
|
namespace Cosmos.Core.Plugs
|
|
{
|
|
[Plug(Target = typeof(global::Cosmos.Core.ProcessorInformation))]
|
|
public unsafe class ProcessorInformationImpl
|
|
{
|
|
private static int* __cyclesrdtscptr; // I declare this as an extra field due to reflection -- don't like it, but can't change it :/
|
|
private static int* __raterdmsrptr; // I declare this as an extra field due to reflection -- don't like it, but can't change it :/
|
|
private static int* __vendortargetptr; // I declare this as an extra field due to reflection -- don't like it, but can't change it :/
|
|
private static long __ticktate = -1;
|
|
|
|
|
|
public static long GetCycleCount()
|
|
{
|
|
int[] val = new int[2];
|
|
|
|
fixed (int* ptr = val)
|
|
__cyclesrdtsc(ptr);
|
|
|
|
return ((long)val[0] << 32) | (uint)val[1];
|
|
}
|
|
|
|
public static long GetCycleRate()
|
|
{
|
|
if (__ticktate == -1)
|
|
{
|
|
int[] raw = new int[4];
|
|
|
|
fixed (int* ptr = raw)
|
|
__raterdmsr(ptr);
|
|
|
|
ulong l1 = ((ulong)raw[0] << 32) | (uint)raw[1];
|
|
ulong l2 = ((ulong)raw[2] << 32) | (uint)raw[3];
|
|
|
|
__ticktate = (long)((double)l2 / (double)l1); // * cpu_rate
|
|
}
|
|
|
|
return __ticktate;
|
|
}
|
|
|
|
[Inline]
|
|
private static void __cyclesrdtsc(int* target)
|
|
{
|
|
/*
|
|
* push eax
|
|
* push ecx
|
|
* push edx
|
|
* lea esi, target
|
|
* rdtsc
|
|
* mov [esi+4], eax
|
|
* mov [esi], edx
|
|
* pop edx
|
|
* pop ecx
|
|
* pop eax
|
|
* ret
|
|
*/
|
|
__cyclesrdtscptr = target;
|
|
|
|
string intname = LabelName.GetFullName(typeof(CPUImpl).GetField(nameof(__cyclesrdtscptr)));
|
|
|
|
ElementReference targ = ElementReference.New(intname);
|
|
new Push
|
|
{
|
|
DestinationReg = RegistersEnum.EAX
|
|
};
|
|
new Push
|
|
{
|
|
DestinationReg = RegistersEnum.ECX
|
|
};
|
|
new Push
|
|
{
|
|
DestinationReg = RegistersEnum.EDX
|
|
};
|
|
new Lea
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
SourceRef = targ,
|
|
};
|
|
new Rdtsc();
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 4,
|
|
SourceReg = RegistersEnum.EAX,
|
|
};
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
SourceReg = RegistersEnum.EDX,
|
|
};
|
|
new Pop
|
|
{
|
|
DestinationReg = RegistersEnum.EDX
|
|
};
|
|
new Pop
|
|
{
|
|
DestinationReg = RegistersEnum.ECX
|
|
};
|
|
new Pop
|
|
{
|
|
DestinationReg = RegistersEnum.EAX
|
|
};
|
|
new Return();
|
|
}
|
|
|
|
[Inline]
|
|
private static void __raterdmsr(int* target)
|
|
{
|
|
/*
|
|
* ; esi register layout: (mperf_hi, mperf_lo, aperf_hi, aperf_lo)
|
|
* ;
|
|
* ; int* ptr = new int[4];
|
|
* ;
|
|
* lea esi, ptr ;equivalent with `mov esi, &ptr`
|
|
* mov ecx, e7h
|
|
* rdmsr
|
|
* mov [esi + 4], eax
|
|
* mov [esi], edx
|
|
* mov ecx, e8h
|
|
* rdmsr
|
|
* mov [esi + 12], eax
|
|
* mov [esi + 8], edx
|
|
* xor eax, eax ;reset to zero
|
|
* ret
|
|
*/
|
|
__raterdmsrptr = target;
|
|
|
|
string intname = LabelName.GetFullName(typeof(CPUImpl).GetField(nameof(__raterdmsrptr)));
|
|
|
|
ElementReference targ = ElementReference.New(intname);
|
|
new Lea
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
SourceRef = targ,
|
|
};
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ECX,
|
|
SourceValue = 0xe7,
|
|
};
|
|
new Rdmsr();
|
|
new Mov
|
|
{
|
|
SourceReg = RegistersEnum.EAX,
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 4,
|
|
};
|
|
new Mov
|
|
{
|
|
SourceReg = RegistersEnum.EDX,
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 0,
|
|
};
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ECX,
|
|
SourceValue = 0xe8,
|
|
};
|
|
new Rdmsr();
|
|
new Mov
|
|
{
|
|
SourceReg = RegistersEnum.EAX,
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 12,
|
|
};
|
|
new Mov
|
|
{
|
|
SourceReg = RegistersEnum.EDX,
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 8,
|
|
};
|
|
new Xor
|
|
{
|
|
SourceReg = RegistersEnum.EAX,
|
|
DestinationReg = RegistersEnum.EAX,
|
|
};
|
|
new Return();
|
|
}
|
|
|
|
[Inline]
|
|
internal static void fetchcpuvendor(int* target)
|
|
{
|
|
/*
|
|
* lea esi, target
|
|
* xor eax, eax
|
|
* cpuid
|
|
* mov [esi], ebx
|
|
* mov [esi + 4], edx
|
|
* mov [esi + 8], ecx
|
|
* ret
|
|
*/
|
|
__vendortargetptr = target;
|
|
|
|
string intname = LabelName.GetFullName(typeof(CPUImpl).GetField(nameof(__vendortargetptr)));
|
|
|
|
ElementReference targ = ElementReference.New(intname);
|
|
new Lea
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
SourceRef = targ,
|
|
};
|
|
new CpuId();
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
SourceReg = RegistersEnum.EBX,
|
|
};
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 4,
|
|
SourceReg = RegistersEnum.EDX,
|
|
};
|
|
new Mov
|
|
{
|
|
DestinationReg = RegistersEnum.ESI,
|
|
DestinationIsIndirect = true,
|
|
DestinationDisplacement = 8,
|
|
SourceReg = RegistersEnum.ECX,
|
|
};
|
|
new Return();
|
|
}
|
|
|
|
[Inline]
|
|
internal static int canreadcpuid()
|
|
{
|
|
/*
|
|
* pushfd
|
|
* pushfd
|
|
* xor dword [esp], 00200000h
|
|
* popfd
|
|
* pushfd
|
|
* pop eax
|
|
* xor eax, [esp]
|
|
* and eax, 00200000h
|
|
* ret
|
|
*/
|
|
new Pushfd();
|
|
new Pushfd();
|
|
new Xor
|
|
{
|
|
DestinationReg = RegistersEnum.ESP,
|
|
DestinationIsIndirect = true,
|
|
SourceValue = 0x00200000
|
|
};
|
|
new Popfd();
|
|
new Pushfd();
|
|
new Pop
|
|
{
|
|
DestinationReg = RegistersEnum.EAX,
|
|
};
|
|
new Xor
|
|
{
|
|
DestinationReg = RegistersEnum.EAX,
|
|
SourceReg = RegistersEnum.ESP,
|
|
SourceIsIndirect = true
|
|
};
|
|
new Popfd();
|
|
new And
|
|
{
|
|
DestinationReg = RegistersEnum.EAX,
|
|
SourceValue = 0x00200000
|
|
};
|
|
new Return();
|
|
return 0;
|
|
}
|
|
}
|
|
}
|