diff --git a/SuperVM.Assembler/Assembler.cs b/SuperVM.Assembler/Assembler.cs
index 04db48e..dd38663 100644
--- a/SuperVM.Assembler/Assembler.cs
+++ b/SuperVM.Assembler/Assembler.cs
@@ -181,17 +181,7 @@ namespace SuperVM.Assembler
}
}
- ulong encoded = 0;
-
- encoded |= ((uint)(instruction.ExecutionZ) << 0);
- encoded |= ((uint)(instruction.ExecutionN) << 2);
- encoded |= ((uint)(instruction.Input0) << 4);
- encoded |= ((uint)(instruction.Input1) << 6);
- encoded |= ((uint)(instruction.Command) << 7);
- encoded |= ((uint)(instruction.CommandInfo) << 13);
- encoded |= ((uint)(instruction.ModifyFlags ? 1 : 0) << 29);
- encoded |= ((uint)(instruction.Output) << 30);
- encoded |= ((ulong)argument << 32);
+ ulong encoded = instruction.Encode();
code.Add(encoded);
instructions.Add(instruction);
diff --git a/SuperVM.Assembler/SuperVM.Assembler.csproj b/SuperVM.Assembler/SuperVM.Assembler.csproj
index a69f90f..fcf4b2f 100644
--- a/SuperVM.Assembler/SuperVM.Assembler.csproj
+++ b/SuperVM.Assembler/SuperVM.Assembler.csproj
@@ -33,6 +33,10 @@
4
+
+ ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll
+ True
+
@@ -51,6 +55,7 @@
+
diff --git a/SuperVM.Assembler/packages.config b/SuperVM.Assembler/packages.config
new file mode 100644
index 0000000..273ff53
--- /dev/null
+++ b/SuperVM.Assembler/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/SuperVM.ExperimentalHost/App.config b/SuperVM.ExperimentalHost/App.config
new file mode 100644
index 0000000..2d2a12d
--- /dev/null
+++ b/SuperVM.ExperimentalHost/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/SuperVM.ExperimentalHost/Program.cs b/SuperVM.ExperimentalHost/Program.cs
new file mode 100644
index 0000000..9c9cb3a
--- /dev/null
+++ b/SuperVM.ExperimentalHost/Program.cs
@@ -0,0 +1,215 @@
+using ICSharpCode.SharpZipLib.Core;
+using ICSharpCode.SharpZipLib.Zip;
+using System;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SuperVM.ExperimentalHost
+{
+ class Program
+ {
+ private static bool running;
+
+ static void Main(string[] args)
+ {
+ var zf = new ZipFile("executable.zip");
+
+ NameValueCollection meta;
+ var metaConfFile = zf.GetEntry("meta.conf");
+ using (var stream = zf.GetInputStream(metaConfFile))
+ {
+ meta = ReadConfiguration(stream);
+ }
+
+ // Default memory size to
+ int memsize = int.Parse(meta["memsize"] ?? "16384");
+
+ var codeName = meta["code"] ?? "code.bin";
+ var dataName = meta["data"];
+
+ if (codeName == null)
+ throw new InvalidDataException();
+
+ Module module;
+ { // Load code
+ var codeFile = zf.GetEntry(codeName);
+ var bits = new byte[codeFile.Size];
+ using (var stream = zf.GetInputStream(codeFile))
+ {
+ for (int i = 0; i < bits.Length; i += stream.Read(bits, i, bits.Length - i)) ;
+ }
+ var instr = new ulong[bits.Length / sizeof(ulong)];
+ Buffer.BlockCopy(bits, 0, instr, 0, instr.Length * sizeof(ulong));
+
+ module = new Module(instr.Select(Instruction.Decode).ToArray());
+ }
+
+ byte[] initialMemory = null;
+ if (dataName != null)
+ {
+ var dataFile = zf.GetEntry(dataName);
+ using (var stream = zf.GetInputStream(dataFile))
+ {
+ using (var ms = new MemoryStream())
+ {
+ stream.CopyTo(ms);
+ initialMemory = ms.ToArray();
+ }
+ }
+ }
+
+ Memory memory = new Memory(memsize);
+ if (initialMemory != null)
+ {
+ Array.Copy(initialMemory, memory.Raw, Math.Min(initialMemory.Length, memsize));
+ }
+
+ var process = new Process(module, memory);
+ process.SysCall += Process_SysCall;
+
+ running = true;
+ var watch = Stopwatch.StartNew();
+ long instructions = 0;
+ while (running)
+ {
+ process.Step();
+ instructions++;
+ }
+ watch.Stop();
+
+ Console.WriteLine();
+ Console.WriteLine("Time: {0}", watch.Elapsed);
+ Console.WriteLine("Count: {0}", instructions);
+ Console.WriteLine("IPS: {0}", instructions / watch.Elapsed.TotalSeconds);
+
+ Console.ReadLine();
+ }
+
+ private static void Process_SysCall(object sender, Process.CommandExecutionEnvironment e)
+ {
+ switch (e.Additional)
+ {
+ case 0: running = false; break;
+ case 1: // putc
+ Console.Write((char)(e.Input0 & 0xFF));
+ break;
+ case 2: // puti
+ Console.Write(e.Input0);
+ break;
+ default:
+ throw new InvalidOperationException("Unkown syscall: " + e.Additional);
+ }
+ }
+
+ static NameValueCollection ReadConfiguration(Stream stream)
+ {
+ var nvc = new NameValueCollection();
+ using (var reader = new StreamReader(stream, Encoding.ASCII))
+ {
+ while (!reader.EndOfStream)
+ {
+ var line = reader.ReadLine();
+ if (line.StartsWith("#"))
+ continue;
+ var parts = line.Split('=');
+ if (parts.Length != 2)
+ throw new InvalidDataException();
+ nvc[parts[0].Trim()] = parts[1].Trim();
+ }
+ }
+ return nvc;
+ }
+
+ // Calling example:
+ // WebClient webClient = new WebClient();
+ // Stream data = webClient.OpenRead("http://www.example.com/test.zip");
+ // This stream cannot be opened with the ZipFile class because CanSeek is false.
+ // UnzipFromStream(data, @"c:\temp");
+
+ public void UnzipFromStream(Stream zipStream, string outFolder)
+ {
+ ZipInputStream zipInputStream = new ZipInputStream(zipStream);
+ ZipEntry zipEntry = zipInputStream.GetNextEntry();
+ while (zipEntry != null)
+ {
+ String entryFileName = zipEntry.Name;
+ // to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
+ // Optionally match entrynames against a selection list here to skip as desired.
+ // The unpacked length is available in the zipEntry.Size property.
+
+ byte[] buffer = new byte[4096]; // 4K is optimum
+
+ // Manipulate the output filename here as desired.
+ String fullZipToPath = Path.Combine(outFolder, entryFileName);
+ string directoryName = Path.GetDirectoryName(fullZipToPath);
+ if (directoryName.Length > 0)
+ Directory.CreateDirectory(directoryName);
+
+ // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
+ // of the file, but does not waste memory.
+ // The "using" will close the stream even if an exception occurs.
+ using (FileStream streamWriter = File.Create(fullZipToPath))
+ {
+ StreamUtils.Copy(zipInputStream, streamWriter, buffer);
+ }
+ zipEntry = zipInputStream.GetNextEntry();
+ }
+ }
+
+
+ public void ExtractZipFile(string archiveFilenameIn, string password, string outFolder)
+ {
+ ZipFile zf = null;
+ try
+ {
+ FileStream fs = File.OpenRead(archiveFilenameIn);
+ zf = new ZipFile(fs);
+ if (!String.IsNullOrEmpty(password))
+ {
+ zf.Password = password; // AES encrypted entries are handled automatically
+ }
+ foreach (ZipEntry zipEntry in zf)
+ {
+ if (!zipEntry.IsFile)
+ {
+ continue; // Ignore directories
+ }
+ String entryFileName = zipEntry.Name;
+ // to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
+ // Optionally match entrynames against a selection list here to skip as desired.
+ // The unpacked length is available in the zipEntry.Size property.
+
+ byte[] buffer = new byte[4096]; // 4K is optimum
+ Stream zipStream = zf.GetInputStream(zipEntry);
+
+ // Manipulate the output filename here as desired.
+ String fullZipToPath = Path.Combine(outFolder, entryFileName);
+ string directoryName = Path.GetDirectoryName(fullZipToPath);
+ if (directoryName.Length > 0)
+ Directory.CreateDirectory(directoryName);
+
+ // Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
+ // of the file, but does not waste memory.
+ // The "using" will close the stream even if an exception occurs.
+ using (FileStream streamWriter = File.Create(fullZipToPath))
+ {
+ StreamUtils.Copy(zipStream, streamWriter, buffer);
+ }
+ }
+ }
+ finally
+ {
+ if (zf != null)
+ {
+ zf.IsStreamOwner = true; // Makes close also shut the underlying stream
+ zf.Close(); // Ensure we release resources
+ }
+ }
+ }
+ }
+}
diff --git a/SuperVM.ExperimentalHost/Properties/AssemblyInfo.cs b/SuperVM.ExperimentalHost/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d3d14c6
--- /dev/null
+++ b/SuperVM.ExperimentalHost/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die einer Assembly zugeordnet sind.
+[assembly: AssemblyTitle("SuperVM.ExperimentalHost")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SuperVM.ExperimentalHost")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("4fe5c136-c634-4ec5-a373-13b1a18a3a2b")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/SuperVM.ExperimentalHost/SuperVM.ExperimentalHost.csproj b/SuperVM.ExperimentalHost/SuperVM.ExperimentalHost.csproj
new file mode 100644
index 0000000..dec7d08
--- /dev/null
+++ b/SuperVM.ExperimentalHost/SuperVM.ExperimentalHost.csproj
@@ -0,0 +1,83 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {4FE5C136-C634-4EC5-A373-13B1A18A3A2B}
+ Exe
+ Properties
+ SuperVM.ExperimentalHost
+ SuperVM.ExperimentalHost
+ v4.6
+ 512
+ true
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ Always
+
+
+
+ ..\packages\SharpZipLib.0.86.0\lib\20\ICSharpCode.SharpZipLib.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {014295b7-06bd-47c7-b8ca-d046984b0f35}
+ SuperVM
+
+
+
+
+
+
+
+ $(SolutionDir)SuperVM.Assembler\bin\Debug\SuperVM.Assembler.exe $(ProjectDir)demo.asm
+cp $(ProjectDir)demo.bin $(TargetDir)code.bin
+$(TargetDir)pack.bat
+
+
+
\ No newline at end of file
diff --git a/SuperVM.ExperimentalHost/demo.asm b/SuperVM.ExperimentalHost/demo.asm
new file mode 100644
index 0000000..86d0fb6
--- /dev/null
+++ b/SuperVM.ExperimentalHost/demo.asm
@@ -0,0 +1,13 @@
+
+
+
+main:
+ push 0 ; ptr
+loop:
+ [i0:peek] load [f:yes]
+ [ex(z)=1] jmp @end
+ [i0:pop] syscall [ci:1]
+ [i0:arg] [i1:pop] add 1
+ jmp @loop
+end:
+ syscall [ci:0] ; quit
\ No newline at end of file
diff --git a/SuperVM.ExperimentalHost/demo.bin b/SuperVM.ExperimentalHost/demo.bin
new file mode 100644
index 0000000..d8b5d7f
Binary files /dev/null and b/SuperVM.ExperimentalHost/demo.bin differ
diff --git a/SuperVM.ExperimentalHost/packages.config b/SuperVM.ExperimentalHost/packages.config
new file mode 100644
index 0000000..7310888
--- /dev/null
+++ b/SuperVM.ExperimentalHost/packages.config
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/SuperVM.sln b/SuperVM.sln
index b348cd0..be29d74 100644
--- a/SuperVM.sln
+++ b/SuperVM.sln
@@ -9,6 +9,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperVM", "SuperVM\SuperVM.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperVM.Assembler", "SuperVM.Assembler\SuperVM.Assembler.csproj", "{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperVM.ExperimentalHost", "SuperVM.ExperimentalHost\SuperVM.ExperimentalHost.csproj", "{4FE5C136-C634-4EC5-A373-13B1A18A3A2B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A84B2773-0EB8-4F3A-B342-68DDD9BD675E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4FE5C136-C634-4EC5-A373-13B1A18A3A2B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/SuperVM/Instruction.cs b/SuperVM/Instruction.cs
index ce6090f..1918db2 100644
--- a/SuperVM/Instruction.cs
+++ b/SuperVM/Instruction.cs
@@ -17,5 +17,39 @@ namespace SuperVM
public bool ModifyFlags;
public OutputType Output;
public uint Argument;
+
+ public override string ToString() => $"({Input0},{Input1}) {Command} -> {Output}";
+
+ public ulong Encode()
+ {
+ ulong encoded = 0;
+ encoded |= ((uint)(this.ExecutionZ) << 0);
+ encoded |= ((uint)(this.ExecutionN) << 2);
+ encoded |= ((uint)(this.Input0) << 4);
+ encoded |= ((uint)(this.Input1) << 6);
+ encoded |= ((uint)(this.Command) << 7);
+ encoded |= ((uint)(this.CommandInfo) << 13);
+ encoded |= ((uint)(this.ModifyFlags ? 1 : 0) << 29);
+ encoded |= ((uint)(this.Output) << 30);
+ encoded |= ((ulong)this.Argument << 32);
+ return encoded;
+ }
+
+ public static Instruction Decode(ulong encoded)
+ {
+ var instr = new Instruction();
+
+ instr.ExecutionZ = (ExecutionMode)((encoded >> 0) & 3);
+ instr.ExecutionN = (ExecutionMode)((encoded >> 2) & 3);
+ instr.Input0 = (InputType)((encoded >> 4) & 3);
+ instr.Input1 = (InputType)((encoded >> 6) & 1);
+ instr.Command = (Command)((encoded >> 7) & 63);
+ instr.CommandInfo = (ushort)((encoded >> 13) & 65535);
+ instr.ModifyFlags = ((encoded >> 29) & 1) != 0;
+ instr.Output = (OutputType)((encoded >> 30) & 3);
+ instr.Argument = (uint)(encoded >> 32);
+
+ return instr;
+ }
}
}
diff --git a/SuperVM/Process.Commands.cs b/SuperVM/Process.Commands.cs
index 4487187..81aaffa 100644
--- a/SuperVM/Process.Commands.cs
+++ b/SuperVM/Process.Commands.cs
@@ -8,6 +8,12 @@ namespace SuperVM
{
partial class Process
{
+ public Process(Module module, Memory memory)
+ {
+ this.Module = module;
+ this.Memory = memory;
+ }
+
private static class Cmd
{
diff --git a/SuperVM/Process.cs b/SuperVM/Process.cs
index 78cfbe6..fb14ee3 100644
--- a/SuperVM/Process.cs
+++ b/SuperVM/Process.cs
@@ -167,7 +167,7 @@ namespace SuperVM
public Module Module { get; set; }
- public Memory Memory { get; set; }
+ public Memory Memory { get; set; } = new Memory(16384);
public uint CodePointer { get; set; }
public uint StackPointer { get; set; }
@@ -189,12 +189,34 @@ namespace SuperVM
this.Process = process;
}
+ ///
+ /// First input value
+ ///
public uint Input0 { get; set; }
+
+ ///
+ /// Second input value
+ ///
public uint Input1 { get; set; }
+
+ ///
+ /// The command argument
+ ///
public uint Argument { get; set; }
+
+ ///
+ /// The command info
+ ///
public uint Additional { get; set; }
+
+ ///
+ /// The output of the command.
+ ///
public uint Output { get; set; }
+ ///
+ /// The executing process.
+ ///
public Process Process { get; private set; }
}
}