mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 04:18:43 +00:00
Merge branch 'master' into ldindreftest
This commit is contained in:
commit
a05cb3a9d4
21 changed files with 222 additions and 376 deletions
|
|
@ -216,7 +216,7 @@ namespace Cosmos.TestRunner.Core
|
|||
"EnableDebug:True",
|
||||
"EnableStackCorruptionDetection:" + EnableStackCorruptionChecks,
|
||||
"StackCorruptionDetectionLevel:" + StackCorruptionDetectionLevel,
|
||||
"DebugMode:Source",
|
||||
"DebugMode:" + DebugMode,
|
||||
"TraceAssemblies:" + TraceAssembliesLevel,
|
||||
"DebugCom:1",
|
||||
"TargetAssembly:" + kernelFileName,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ namespace Cosmos.TestRunner.Core
|
|||
protected TraceAssemblies TraceAssembliesLevel => mConfiguration.TraceAssembliesLevel;
|
||||
protected bool EnableStackCorruptionChecks => mConfiguration.EnableStackCorruptionChecks;
|
||||
protected StackCorruptionDetectionLevel StackCorruptionDetectionLevel => mConfiguration.StackCorruptionDetectionLevel;
|
||||
protected DebugMode DebugMode => mConfiguration.DebugMode;
|
||||
|
||||
protected bool RunWithGDB => mConfiguration.RunWithGDB;
|
||||
protected bool StartBochsDebugGui => mConfiguration.StartBochsDebugGUI;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace Cosmos.TestRunner.Core
|
|||
TraceAssemblies TraceAssembliesLevel { get; }
|
||||
bool EnableStackCorruptionChecks { get; }
|
||||
StackCorruptionDetectionLevel StackCorruptionDetectionLevel { get; }
|
||||
DebugMode DebugMode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// An enumerable of kernel assemblies which will be run.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ namespace Cosmos.TestRunner.Full
|
|||
public virtual TraceAssemblies TraceAssembliesLevel => TraceAssemblies.User;
|
||||
public virtual bool EnableStackCorruptionChecks => true;
|
||||
public virtual StackCorruptionDetectionLevel StackCorruptionDetectionLevel => StackCorruptionDetectionLevel.AllInstructions;
|
||||
public virtual DebugMode DebugMode => DebugMode.Source;
|
||||
|
||||
public virtual IEnumerable<string> KernelAssembliesToRun
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ namespace Cosmos.TestRunner.TestAdapter
|
|||
public TraceAssemblies TraceAssembliesLevel { get; }
|
||||
public bool EnableStackCorruptionChecks { get; }
|
||||
public StackCorruptionDetectionLevel StackCorruptionDetectionLevel { get; }
|
||||
public DebugMode DebugMode { get; }
|
||||
|
||||
public IEnumerable<string> KernelAssembliesToRun { get; }
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ namespace Cosmos.TestRunner.UI.ViewModels
|
|||
set => SetProperty(ref mStackCorruptionDetectionLevel, value);
|
||||
}
|
||||
|
||||
private DebugMode mDebugMode = defaultEngineConfiguration.DebugMode;
|
||||
public DebugMode DebugMode
|
||||
{
|
||||
get => mDebugMode;
|
||||
set => SetProperty(ref mDebugMode, value);
|
||||
}
|
||||
|
||||
public IEnumerable<string> KernelAssembliesToRun
|
||||
{
|
||||
get
|
||||
|
|
|
|||
25
Tests/Cosmos.TestRunner/.vscode/launch.json
vendored
25
Tests/Cosmos.TestRunner/.vscode/launch.json
vendored
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
"program": "${workspaceFolder}/bin/Debug/netcoreapp2.0/Cosmos.TestRunner.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
Tests/Cosmos.TestRunner/.vscode/tasks.json
vendored
42
Tests/Cosmos.TestRunner/.vscode/tasks.json
vendored
|
|
@ -1,42 +0,0 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/Cosmos.TestRunner.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/Cosmos.TestRunner.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/Cosmos.TestRunner.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -39,6 +39,7 @@ namespace Cosmos.Compiler.Tests.Bcl
|
|||
DelegatesTest.Execute();
|
||||
EventsTest.Execute();
|
||||
RandomTests.Execute();
|
||||
ConvertTests.Execute();
|
||||
|
||||
// System.Collections
|
||||
HashtableTest.Execute();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
using Cosmos.TestRunner;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Cosmos.Compiler.Tests.Bcl.System
|
||||
{
|
||||
public static class ConvertTests
|
||||
{
|
||||
public static void Execute()
|
||||
{
|
||||
Assert.AreEqual("1010", Convert.ToString(10, 2), "Convert.ToString(int, 2) works");
|
||||
Assert.AreEqual("12", Convert.ToString(10, 8), "Convert.ToString(int, 8) works");
|
||||
Assert.AreEqual("10", Convert.ToString(10, 10), "Convert.ToString(int, 10) works");
|
||||
Assert.AreEqual("A", Convert.ToString(10, 16), "Convert.ToString(int, 16) works");
|
||||
Assert.AreEqual("11000100000", Convert.ToString(1568, 2), "Convert.ToString(int, 2) works");
|
||||
Assert.AreEqual("3040", Convert.ToString(1568, 8), "Convert.ToString(int, 8) works");
|
||||
Assert.AreEqual("1568", Convert.ToString(1568, 10), "Convert.ToString(int, 10) works");
|
||||
Assert.AreEqual("620", Convert.ToString(1568, 16), "Convert.ToString(int, 16) works");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ namespace Cosmos.Kernel.Tests.Fat.System.IO
|
|||
/// </summary>
|
||||
public static void Execute(Debugger mDebugger)
|
||||
{
|
||||
|
||||
mDebugger.Send("START TEST: Delete a directory:");
|
||||
Directory.CreateDirectory(@"0:\TestDir1");
|
||||
Assert.IsTrue(Directory.Exists(@"0:\TestDir1"), "TestDir1 wasn't created!");
|
||||
|
|
@ -97,22 +96,20 @@ namespace Cosmos.Kernel.Tests.Fat.System.IO
|
|||
|
||||
mDebugger.Send("");
|
||||
|
||||
#if false
|
||||
mDebugger.Send("START TEST: Delete a file with Directory.Delete:");
|
||||
File.Create(@"0:\file1.txt");
|
||||
mDebugger.Send("START TEST: Creating a subdirecty with Directory.CreateDirectory:");
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(@"0:\file1.txt");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Assert.IsTrue(File.Exists(@"0:\file1.txt"), "The file was deleted by Directory.Delete.");
|
||||
}
|
||||
Directory.CreateDirectory(@"0:\TestDir1");
|
||||
Assert.IsTrue(Directory.Exists(@"0:\TestDir1"), "TestDir1 was created!");
|
||||
Directory.CreateDirectory(@"0:\TestDir1\test");
|
||||
Assert.IsTrue(Directory.Exists(@"0:\TestDir1\test"), "test subdirectory was created!");
|
||||
Directory.Delete(@"0:\TestDir1\test");
|
||||
Assert.IsFalse(Directory.Exists(@"0:\TestDir1\test"), "test subdirectory was deleted!");
|
||||
Directory.Delete(@"0:\TestDir1");
|
||||
Assert.IsFalse(Directory.Exists(@"0:\TestDir1"), "TestDir1 was deleted!");
|
||||
|
||||
mDebugger.Send("END TEST");
|
||||
mDebugger.Send("");
|
||||
#endif
|
||||
|
||||
|
||||
mDebugger.Send("START TEST: Create a directory with a Long Filename:");
|
||||
Directory.CreateDirectory(@"0:\TestDir1");
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@ namespace ProcessorTests
|
|||
}
|
||||
}
|
||||
|
||||
public void TestBrandStringBlank()
|
||||
{
|
||||
string brandString = CPU.GetCPUBrandString();
|
||||
mDebugger.Send("Brand String: " + brandString);
|
||||
bool isBrandStringBlank = string.IsNullOrWhiteSpace(brandString);
|
||||
Assert.IsFalse(isBrandStringBlank, "Processor brand string is blank.");
|
||||
}
|
||||
|
||||
public void TestVendorNameIsNotBlank()
|
||||
{
|
||||
string vendorName = CPU.GetCPUVendorName();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<PropertyGroup>
|
||||
<ApprovalTestsVersion>3.0.22</ApprovalTestsVersion>
|
||||
<AvaloniaVersion>0.7.0</AvaloniaVersion>
|
||||
<MicrosoftBuildVersion>16.0.461</MicrosoftBuildVersion>
|
||||
<MicrosoftBuildVersion>16.7.0</MicrosoftBuildVersion>
|
||||
<MicrosoftNETFrameworkReferenceAssembliesVersion>1.0.0</MicrosoftNETFrameworkReferenceAssembliesVersion>
|
||||
<MicrosoftNETTestSdkVersion>16.0.1</MicrosoftNETTestSdkVersion>
|
||||
<MicrosoftTestPlatformObjectModelVersion>16.0.1</MicrosoftTestPlatformObjectModelVersion>
|
||||
|
|
|
|||
|
|
@ -110,6 +110,8 @@ namespace Cosmos.Core
|
|||
return xResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get CPU vendor name.
|
||||
/// </summary>
|
||||
|
|
@ -179,15 +181,15 @@ namespace Cosmos.Core
|
|||
{
|
||||
ReadCPUID(0x80000002 + i, ref eax, ref ebx, ref ecx, ref edx);
|
||||
s += (char)(ebx % 256);
|
||||
s += (char)((ebx >> 8) % 256);
|
||||
s += (char)((ebx>> 16) % 256);
|
||||
s += (char)((ebx >> 24) % 256);
|
||||
s += (char)((ebx >> 8) % 256);
|
||||
s += (char)((ebx >> 16) % 256);
|
||||
s += (char)((ebx >> 24) % 256);
|
||||
s += (char)(edx % 256);
|
||||
s += (char)((edx >> 8) % 256);
|
||||
s += (char)((edx >> 16) % 256);
|
||||
s += (char)((edx >> 24) % 256);
|
||||
s += (char)((edx >> 8) % 256);
|
||||
s += (char)((edx >> 16) % 256);
|
||||
s += (char)((edx >> 24) % 256);
|
||||
s += (char)(ecx % 256);
|
||||
s += (char)((ecx >> 8) % 256);
|
||||
s += (char)((ecx >> 8) % 256);
|
||||
s += (char)((ecx >> 16) % 256);
|
||||
s += (char)((ecx >> 24) % 256);
|
||||
}
|
||||
|
|
@ -247,12 +249,73 @@ namespace Cosmos.Core
|
|||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get CPU cycle speed.
|
||||
/// </summary>
|
||||
/// <returns>long value.</returns>
|
||||
/// <exception cref="NotImplementedException">Thrown on fatal error, contact support.</exception>
|
||||
/// <exception cref="NotSupportedException">Thrown if can not read CPU ID.</exception>
|
||||
public static string GetCPUBrandString()
|
||||
{
|
||||
if (CanReadCPUID() != 0)
|
||||
{
|
||||
// See https://c9x.me/x86/html/file_module_x86_id_45.html
|
||||
|
||||
int eax = 0;
|
||||
int ebx = 0;
|
||||
int ecx = 0;
|
||||
int edx = 0;
|
||||
int[] s = new int[64];
|
||||
string rs = "";
|
||||
|
||||
for (uint i = 0; i < 3; i++)
|
||||
{
|
||||
ReadCPUID(0x80000002 + i, ref eax, ref ebx, ref ecx, ref edx);
|
||||
s[(i * 16) + 0] = (eax % 256);
|
||||
s[(i * 16) + 1] = ((eax >> 8) % 256);
|
||||
s[(i * 16) + 2] = ((eax >> 16) % 256);
|
||||
s[(i * 16) + 3] = ((eax >> 24) % 256);
|
||||
s[(i * 16) + 4] = (ebx % 256);
|
||||
s[(i * 16) + 5] = ((ebx >> 8) % 256);
|
||||
s[(i * 16) + 6] = ((ebx >> 16) % 256);
|
||||
s[(i * 16) + 7] = ((ebx >> 24) % 256);
|
||||
s[(i * 16) + 8] = (ecx % 256);
|
||||
s[(i * 16) + 9] = ((ecx >> 8) % 256);
|
||||
s[(i * 16) + 10] = ((ecx >> 16) % 256);
|
||||
s[(i * 16) + 11] = ((ecx >> 24) % 256);
|
||||
s[(i * 16) + 12] = (edx % 256);
|
||||
s[(i * 16) + 13] = ((edx >> 8) % 256);
|
||||
s[(i * 16) + 14] = ((edx >> 16) % 256);
|
||||
s[(i * 16) + 15] = ((edx >> 24) % 256);
|
||||
}
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
if (s[i] == 0x00)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
rs += (char)s[i];
|
||||
}
|
||||
|
||||
if (!(rs == ""))
|
||||
{
|
||||
return rs;
|
||||
} else
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Check if can read CPU ID. Plugged.
|
||||
/// </summary>
|
||||
/// <returns>non-zero if can read.</returns>
|
||||
/// <exception cref="NotImplementedException">Thrown on fatal error, contact support.</exception>
|
||||
internal static int CanReadCPUID() => throw new NotImplementedException();
|
||||
public static int CanReadCPUID() => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Read CPU ID. Plugged.
|
||||
|
|
@ -263,7 +326,7 @@ namespace Cosmos.Core
|
|||
/// <param name="ecx">ecx.</param>
|
||||
/// <param name="edx">edx.</param>
|
||||
/// <exception cref="NotImplementedException">Thrown on fatal error, contact support.</exception>
|
||||
internal static void ReadCPUID(uint type, ref int eax, ref int ebx, ref int ecx, ref int edx) => throw new NotImplementedException();
|
||||
public static void ReadCPUID(uint type, ref int eax, ref int ebx, ref int ecx, ref int edx) => throw new NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Read timestamp counter. Plugged.
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
namespace Cosmos.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// ProcessorInformation class. Used to get vendor information from the CPU.
|
||||
/// </summary>
|
||||
public unsafe class ProcessorInformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the Processor's vendor name
|
||||
/// </summary>
|
||||
/// <returns>CPU Vendor name</returns>
|
||||
public static string GetVendorName()
|
||||
{
|
||||
if (CanReadCPUID() > 0)
|
||||
{
|
||||
int[] raw = new int[3];
|
||||
|
||||
fixed (int* ptr = raw)
|
||||
FetchCPUVendor(ptr);
|
||||
|
||||
return new string(new char[] {
|
||||
(char)(raw[0] >> 24),
|
||||
(char)((raw[0] >> 16) & 0xff),
|
||||
(char)((raw[0] >> 8) & 0xff),
|
||||
(char)(raw[0] & 0xff),
|
||||
(char)(raw[1] >> 24),
|
||||
(char)((raw[1] >> 16) & 0xff),
|
||||
(char)((raw[1] >> 8) & 0xff),
|
||||
(char)(raw[1] & 0xff),
|
||||
(char)(raw[2] >> 24),
|
||||
(char)((raw[2] >> 16) & 0xff),
|
||||
(char)((raw[2] >> 8) & 0xff),
|
||||
(char)(raw[2] & 0xff),
|
||||
});
|
||||
}
|
||||
else
|
||||
return "\0";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if can read CPU ID.
|
||||
/// </summary>
|
||||
/// <returns>int value.</returns>
|
||||
internal static int CanReadCPUID() => 0; //plugged
|
||||
|
||||
/// <summary>
|
||||
/// Fetch CPU vendor.
|
||||
/// </summary>
|
||||
/// <param name="target">pointer to target.</param>
|
||||
internal static void FetchCPUVendor(int* target) { } //plugged
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of CPU cycles since startup of the current CPU core
|
||||
/// </summary>
|
||||
/// <returns>Number of CPU cycles since startup</returns>
|
||||
public static long GetCycleCount() => 0; //plugged
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of CPU cycles per seconds
|
||||
/// </summary>
|
||||
/// <returns>Number of CPU cycles per seconds</returns>
|
||||
public static long GetCycleRate() => 0; //plugged
|
||||
}
|
||||
}
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
using Cosmos.Core;
|
||||
|
||||
using IL2CPU.API;
|
||||
using IL2CPU.API.Attribs;
|
||||
|
||||
using XSharp;
|
||||
|
||||
namespace Cosmos.Core_Asm
|
||||
{
|
||||
[Plug(Target = typeof(ProcessorInformation))]
|
||||
public unsafe class ProcessorInformationImpl
|
||||
{
|
||||
/* The following three int*-pointers are needed for the lea instruction due to the following reason:
|
||||
* When comiling, the IL-code will be translated into x86-ASM, which has specific and unique names for local variables.
|
||||
* To access these local variables, I have to pass their excat name to the instruction in question. This is rather
|
||||
* difficult with reflection, if these variables reside in the local function scope. For this reason, I move the
|
||||
* pointer to class scope to access them quicker and more easily
|
||||
*/
|
||||
private static int* __cyclesrdtscptr, __raterdmsrptr, __vendortargetptr;
|
||||
private static long __ticktate = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of CPU cycles since startup
|
||||
/// </summary>
|
||||
/// <returns>Number of CPU cycles</returns>
|
||||
public static long GetCycleCount()
|
||||
{
|
||||
int[] val = new int[2];
|
||||
|
||||
fixed (int* ptr = val)
|
||||
{
|
||||
__cyclesrdtsc(ptr);
|
||||
}
|
||||
|
||||
return ((long)val[0] << 32) | (uint)val[1];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the CPU cycle rate (in cycles/µs)
|
||||
/// </summary>
|
||||
/// <returns>CPU cycle rate</returns>
|
||||
public static long GetCycleRate()
|
||||
{
|
||||
if (__ticktate == -1)
|
||||
{
|
||||
int[] raw = new int[4];
|
||||
|
||||
fixed (int* ptr = raw)
|
||||
{
|
||||
__raterdmsr(ptr);
|
||||
}
|
||||
|
||||
ulong l1 = (ulong)__maxrate();
|
||||
ulong l2 = ((ulong)raw[0] << 32) | (uint)raw[1];
|
||||
ulong l3 = ((ulong)raw[2] << 32) | (uint)raw[3];
|
||||
|
||||
__ticktate = (long)l2; // (long)((double)l1 * l3 / l2);
|
||||
}
|
||||
|
||||
return __ticktate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the maximum cpu rate set by the bios at startup to the given int pointer
|
||||
/// </summary>
|
||||
[Inline]
|
||||
private static int __maxrate()
|
||||
{
|
||||
/*
|
||||
* mov eax, 16h
|
||||
* cpuid
|
||||
* and eax, ffffh
|
||||
* ret
|
||||
*/
|
||||
|
||||
XS.Set(XSRegisters.EAX, 0x00000016);
|
||||
XS.Cpuid();
|
||||
XS.And(XSRegisters.EAX, 0x0000ffff);
|
||||
XS.Return();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the cycle count to the given int pointer
|
||||
/// </summary>
|
||||
[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.GetStaticFieldName(typeof(CPUImpl).GetField(nameof(__cyclesrdtscptr)));
|
||||
|
||||
XS.Push(XSRegisters.EAX);
|
||||
XS.Push(XSRegisters.ECX);
|
||||
XS.Push(XSRegisters.EDX);
|
||||
XS.Lea(XSRegisters.ESI, intname);
|
||||
XS.Rdtsc();
|
||||
XS.Set(XSRegisters.ESI, XSRegisters.EAX, destinationIsIndirect: true, destinationDisplacement: 4);
|
||||
XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true);
|
||||
XS.Push(XSRegisters.EDX);
|
||||
XS.Push(XSRegisters.ECX);
|
||||
XS.Push(XSRegisters.EAX);
|
||||
XS.Return();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copies the cycle rate to the given int pointer
|
||||
/// </summary>
|
||||
[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
|
||||
* ret
|
||||
*/
|
||||
__raterdmsrptr = target;
|
||||
|
||||
string intname = LabelName.GetStaticFieldName(typeof(CPUImpl).GetField(nameof(__raterdmsrptr)));
|
||||
|
||||
XS.Lea(XSRegisters.ESI, intname);
|
||||
XS.Set(XSRegisters.ECX, 0xe7);
|
||||
XS.Rdmsr();
|
||||
XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 4);
|
||||
XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 0);
|
||||
XS.Set(XSRegisters.ECX, 0xe8);
|
||||
XS.Rdmsr();
|
||||
XS.Set(XSRegisters.EAX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 12);
|
||||
XS.Set(XSRegisters.EDX, XSRegisters.ESI, destinationIsIndirect: true, destinationDisplacement: 8);
|
||||
XS.Xor(XSRegisters.EAX, XSRegisters.EAX); // XS.Set(XSRegisters.EAX, 0);
|
||||
XS.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.GetStaticFieldName(typeof(CPUImpl).GetField(nameof(__vendortargetptr)));
|
||||
|
||||
XS.Lea(XSRegisters.ESI, intname); // new Lea { DestinationReg = RegistersEnum.ESI, SourceRef = ElementReference.New(intname) };
|
||||
XS.Cpuid();
|
||||
XS.Set(XSRegisters.ESI, XSRegisters.EBX, destinationIsIndirect: true);
|
||||
XS.Set(XSRegisters.ESI, XSRegisters.EDX, destinationIsIndirect: true, destinationDisplacement: 4);
|
||||
XS.Set(XSRegisters.ESI, XSRegisters.ECX, destinationIsIndirect: true, destinationDisplacement: 8);
|
||||
XS.Return();
|
||||
}
|
||||
|
||||
[Inline]
|
||||
internal static int CanReadCPUID()
|
||||
{
|
||||
/*
|
||||
* pushfd
|
||||
* pushfd
|
||||
* xor dword [esp], 00200000h
|
||||
* popfd
|
||||
* pushfd
|
||||
* pop eax
|
||||
* xor eax, [esp]
|
||||
* and eax, 00200000h
|
||||
* ret
|
||||
*/
|
||||
XS.Pushfd();
|
||||
XS.Pushfd();
|
||||
XS.Xor(XSRegisters.ESP, 0x00200000, destinationIsIndirect: true);
|
||||
XS.Popfd();
|
||||
XS.Pushfd();
|
||||
XS.Pop(XSRegisters.EAX);
|
||||
XS.Xor(XSRegisters.EAX, XSRegisters.ESP, destinationIsIndirect: true);
|
||||
XS.Popfd();
|
||||
XS.And(XSRegisters.EAX, 0x00200000);
|
||||
XS.Return();
|
||||
|
||||
return 0; // should be ignored by the compiler
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,7 @@ namespace Cosmos.Core_Plugs.System.Diagnostics
|
|||
{
|
||||
if (Stopwatch.IsHighResolution)
|
||||
// see https://msdn.microsoft.com/en-us/library/windows/desktop/dn553408(v=vs.85).aspx for more details
|
||||
return (long)(ProcessorInformation.GetCycleCount() / (double)ProcessorInformation.GetCycleRate() * 1000000d);
|
||||
return (long)(CPU.GetCPUUptime() / (double)CPU.GetCPUUptime() * 1000000d);
|
||||
else
|
||||
return DateTime.UtcNow.Ticks;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,10 +23,10 @@ namespace Cosmos.Core_Plugs.System.Threading
|
|||
|
||||
// if ((ms > 0) && (ms != Timeout.Infinite))
|
||||
// {
|
||||
// double fac = ProcessorInformation.GetCycleRate() / 1000d;
|
||||
// double ticks = ms / 1000d * Stopwatch.Frequency + ProcessorInformation.GetCycleCount() * fac;
|
||||
// double fac = CPU.GetCycleRate() / 1000d;
|
||||
// double ticks = ms / 1000d * Stopwatch.Frequency + CPU.GetCycleCount() * fac;
|
||||
|
||||
// while (ticks < ProcessorInformation.GetCycleCount() * fac)
|
||||
// while (ticks < CPU.GetCycleCount() * fac)
|
||||
// new Action(() => { }).Invoke(); // execute an empty operation
|
||||
// }
|
||||
// else if (ms < 0)
|
||||
|
|
|
|||
|
|
@ -512,6 +512,8 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
/// <exception cref="NotSupportedException">Thrown when FAT type is unknown.</exception>
|
||||
public void DeleteDirectoryEntry()
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.DeleteDirectoryEntry --");
|
||||
|
||||
if (mEntryType == DirectoryEntryTypeEnum.Unknown)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
|
|
@ -524,12 +526,17 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
|
||||
var xData = ((FatDirectoryEntry)mParent).GetDirectoryEntryData();
|
||||
|
||||
var xEntryOffset = mEntryHeaderDataOffset - 32;
|
||||
|
||||
while (xData[xEntryOffset + 11] == FatDirectoryEntryAttributeConsts.LongName)
|
||||
if(mEntryHeaderDataOffset > 32)
|
||||
{
|
||||
xData[xEntryOffset] = FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry;
|
||||
xEntryOffset -= 32;
|
||||
var xEntryOffset = mEntryHeaderDataOffset - 32;
|
||||
|
||||
Global.mFileSystemDebugger.SendInternal("xEntryOffset: " + xEntryOffset);
|
||||
|
||||
while (xData[xEntryOffset + 11] == FatDirectoryEntryAttributeConsts.LongName)
|
||||
{
|
||||
xData[xEntryOffset] = FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry;
|
||||
xEntryOffset -= 32;
|
||||
}
|
||||
}
|
||||
|
||||
((FatDirectoryEntry)mParent).SetDirectoryEntryData(xData);
|
||||
|
|
@ -988,6 +995,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, byte aValue)
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal(" -- FatDirectoryEntry.SetDirectoryEntryMetadataValue(uint) --");
|
||||
Global.mFileSystemDebugger.SendInternal("aEntryMetadata = " + aEntryMetadata.DataOffset);
|
||||
Global.mFileSystemDebugger.SendInternal("aValue = " + aValue);
|
||||
|
||||
if (IsRootDirectory())
|
||||
|
|
@ -1043,6 +1051,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, ushort aValue)
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal(" -- FatDirectoryEntry.SetDirectoryEntryMetadataValue(uint) --");
|
||||
Global.mFileSystemDebugger.SendInternal("aEntryMetadata = " + aEntryMetadata.DataOffset);
|
||||
Global.mFileSystemDebugger.SendInternal("aValue = " + aValue);
|
||||
|
||||
if (IsRootDirectory())
|
||||
|
|
@ -1054,6 +1063,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
|
||||
if (xData.Length > 0)
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal("mEntryHeaderDataOffset = " + mEntryHeaderDataOffset);
|
||||
var xValue = new byte[aEntryMetadata.DataLength];
|
||||
xValue.SetUInt16(0, aValue);
|
||||
uint offset = mEntryHeaderDataOffset + aEntryMetadata.DataOffset;
|
||||
|
|
@ -1100,6 +1110,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, uint aValue)
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal(" -- FatDirectoryEntry.SetDirectoryEntryMetadataValue(uint) --");
|
||||
Global.mFileSystemDebugger.SendInternal("aEntryMetadata = " + aEntryMetadata.DataOffset);
|
||||
Global.mFileSystemDebugger.SendInternal("aValue = " + aValue);
|
||||
|
||||
if (IsRootDirectory())
|
||||
|
|
@ -1157,6 +1168,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, long aValue)
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.SetDirectoryEntryMetadataValue(long) --");
|
||||
Global.mFileSystemDebugger.SendInternal("aEntryMetadata = " + aEntryMetadata.DataOffset);
|
||||
Global.mFileSystemDebugger.SendInternal("aValue =");
|
||||
Global.mFileSystemDebugger.SendInternal(aValue);
|
||||
|
||||
|
|
@ -1218,6 +1230,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
|
|||
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, string aValue)
|
||||
{
|
||||
Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.SetDirectoryEntryMetadataValue(string) --");
|
||||
Global.mFileSystemDebugger.SendInternal("aEntryMetadata = " + aEntryMetadata.DataOffset);
|
||||
Global.mFileSystemDebugger.SendInternal($"aValue = {aValue}");
|
||||
|
||||
if (IsRootDirectory())
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ namespace Cosmos.System_Plugs.System
|
|||
{
|
||||
string result = "";
|
||||
|
||||
if(aThis == 0)
|
||||
{
|
||||
result = "0";
|
||||
}
|
||||
|
||||
while (aThis != 0)
|
||||
{
|
||||
if ((aThis % 16) < 10)
|
||||
|
|
|
|||
68
source/Cosmos.System2_Plugs/System/ParseNumbersImpl.cs
Normal file
68
source/Cosmos.System2_Plugs/System/ParseNumbersImpl.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Cosmos.Common.Extensions;
|
||||
using IL2CPU.API.Attribs;
|
||||
|
||||
namespace Cosmos.System_Plugs.System
|
||||
{
|
||||
[Plug(TargetName = "System.ParseNumbers, System.Private.CoreLib")]
|
||||
class ParseNumbersImpl
|
||||
{
|
||||
public static string IntToString(int value, int radix, int width, char paddingChar, int flags)
|
||||
{
|
||||
if (flags != 0)
|
||||
{
|
||||
throw new NotImplementedException("IntToString with non-zero flags is not supported");
|
||||
}
|
||||
string valueString = "";
|
||||
|
||||
if (radix == 2 || radix == 8 || radix == 16)
|
||||
{
|
||||
int shiftRightAmount = 1;
|
||||
if (radix == 8)
|
||||
{
|
||||
shiftRightAmount = 3;
|
||||
}
|
||||
else if (radix == 16)
|
||||
{
|
||||
shiftRightAmount = 4;
|
||||
}
|
||||
if (value < 0)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
while (value > 0)
|
||||
{
|
||||
valueString = (value % radix).ToString("X") + valueString;
|
||||
value >>= shiftRightAmount;
|
||||
}
|
||||
}
|
||||
else if (radix == 10)
|
||||
{
|
||||
valueString = value.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(nameof(radix));
|
||||
}
|
||||
|
||||
if (width == -1)
|
||||
{
|
||||
return valueString;
|
||||
}
|
||||
|
||||
if (valueString.Length > width)
|
||||
{
|
||||
throw new NotImplementedException("IntToString Case not handled when value is longer than width");
|
||||
}
|
||||
|
||||
int count = width - valueString.Length;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
valueString = paddingChar + valueString;
|
||||
}
|
||||
return valueString;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue