mirror of
https://github.com/creeperlv/SVM.git
synced 2026-01-10 20:39:54 +00:00
Hello world finally works.
Sample working code: .data: text0 "Hello, World!\n" .code: sd.int32 $4 123 sd.int32 $5 321 sd.int32 $10 1 sd.int32 $11 text0 sd.int32 $12 14 sys 4 sd.int32 $10 100 sys 1 bmath add Int32 $4 $5 $6
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using SVM.Core;
|
||||
using SVM.Core.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace SVM.Advanced.BSDStyleVM
|
||||
@@ -14,7 +16,10 @@ namespace SVM.Advanced.BSDStyleVM
|
||||
this.baseVM = baseVM;
|
||||
baseVM.AdditionalData = this;
|
||||
baseVM.Config = BSDConfig.CreateConfig();
|
||||
FDs.Add(0, new FileDescripter(Console.OpenStandardInput()));
|
||||
FDs.Add(1, new FileDescripter(Console.OpenStandardOutput()));
|
||||
}
|
||||
|
||||
}
|
||||
public class BSDConfig
|
||||
{
|
||||
@@ -30,6 +35,7 @@ namespace SVM.Advanced.BSDStyleVM
|
||||
public static void SetupSyscall(SVMConfig config)
|
||||
{
|
||||
config.FuncCalls.Add(1, BSDStyleFunctions0.__exit);
|
||||
config.FuncCalls.Add(4, BSDStyleFunctions0.__write);
|
||||
}
|
||||
}
|
||||
public static class BSDStyleFunctions0
|
||||
@@ -37,9 +43,27 @@ namespace SVM.Advanced.BSDStyleVM
|
||||
public static void __exit(SimpleVirtualMachine machine)
|
||||
{
|
||||
var status = machine.registers.GetData<int>(10);
|
||||
Console.WriteLine("Bye-bye!");
|
||||
Environment.Exit(status);
|
||||
}
|
||||
public static void __write(SimpleVirtualMachine machine)
|
||||
{
|
||||
if (machine.AdditionalData is BSDLikeWrapper w)
|
||||
{
|
||||
var fd = machine.registers.GetData<int>(10);
|
||||
var ptr = machine.registers.GetData<SVMPointer>(11);
|
||||
var size = machine.registers.GetData<ulong>(12);
|
||||
if (w.FDs.TryGetValue(fd, out var descripter))
|
||||
{
|
||||
descripter.stream.WriteData(machine.GetPointer(ptr), size);
|
||||
}
|
||||
else
|
||||
Console.WriteLine($"FD:{fd} does not exist.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Incorrectly set wrapper!");
|
||||
}
|
||||
}
|
||||
}
|
||||
public class FileDescripter
|
||||
{
|
||||
|
||||
@@ -17,6 +17,8 @@ Match:
|
||||
InstMath bmath
|
||||
InstSDInt32 sd\.int32
|
||||
InstSDInt sd\.int
|
||||
InstSDInt64 sd\.int64
|
||||
InstSDLong sd\.long
|
||||
InstCvt cvt
|
||||
InstSystem system
|
||||
InstSys sys
|
||||
@@ -35,6 +37,8 @@ D \d
|
||||
|
||||
Id:
|
||||
word Word
|
||||
InstSDInt64 inst
|
||||
InstSDLong inst
|
||||
InstMath inst
|
||||
InstSDInt inst
|
||||
InstSDInt32 inst
|
||||
@@ -80,7 +84,7 @@ LabelConstant InternalLbl
|
||||
if (r.Result.LexSegmentId != null && r.Result.LexMatchedItemId != null)
|
||||
{
|
||||
if (r.Result.LexSegmentId == "LE") continue;
|
||||
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -128,6 +132,7 @@ LabelConstant InternalLbl
|
||||
operationResult.AddError(new ErrorWMsg($"Unknown Instruction:{LexDef.Content ?? "<null>"}", LexDef));
|
||||
return operationResult;
|
||||
}
|
||||
intermediateInstruction.InstDefID = instructionDef.Id;
|
||||
intermediateInstruction.inst = instructionDef.PrimaryInstruction;
|
||||
foreach (var item in instructionDef.ParameterPattern)
|
||||
{
|
||||
@@ -250,10 +255,26 @@ LabelConstant InternalLbl
|
||||
public Dictionary<string, string> data = new Dictionary<string, string>();
|
||||
public Dictionary<string, string> consts = new Dictionary<string, string>();
|
||||
public List<IntermediateInstruction> instructions = new List<IntermediateInstruction>();
|
||||
public int DetermineFinalInstructionCount(LinkingContext context)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var item in instructions)
|
||||
{
|
||||
if (context.Definition.InstructionDefinitions.TryGetValue(item.InstDefID, out var def))
|
||||
{
|
||||
count += def.InstructionCount;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
public bool TryGetConst(string str, out string value)
|
||||
{
|
||||
return consts.TryGetValue(str, out value);
|
||||
}
|
||||
public bool TryGetDataOffset(string str, out string value)
|
||||
{
|
||||
return consts.TryGetValue(str, out value);
|
||||
}
|
||||
public bool TryGetLabelPC(string label, out int PC)
|
||||
{
|
||||
for (int i = 0; i < instructions.Count; i++)
|
||||
@@ -273,6 +294,7 @@ LabelConstant InternalLbl
|
||||
public class IntermediateInstruction
|
||||
{
|
||||
public LexSegment? Label = null;
|
||||
public string InstDefID = "";
|
||||
public PrimaryInstruction inst;
|
||||
public List<LexSegment> Parameters = new List<LexSegment>();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace SVM.Assembler.Core
|
||||
{
|
||||
public Dictionary<string, byte> RegisterNames = new Dictionary<string, byte>();
|
||||
public Dictionary<string, Dictionary<string, string>> Enums = new Dictionary<string, Dictionary<string, string>>();
|
||||
public Dictionary<PrimaryInstruction, InstructionDefinition> InstructionDefinitions = new Dictionary<PrimaryInstruction, InstructionDefinition>();
|
||||
public Dictionary<string, InstructionDefinition> InstructionDefinitions = new Dictionary<string, InstructionDefinition>();
|
||||
[NonSerialized]
|
||||
public Dictionary<string, InstructionDefinition> InstructionDefinitionAliases = new Dictionary<string, InstructionDefinition>();
|
||||
public void Init()
|
||||
@@ -117,7 +117,11 @@ namespace SVM.Assembler.Core
|
||||
InstructionDefinition instDefinition = new InstructionDefinition();
|
||||
var PIAttr = node.Attributes.GetNamedItem("PrimaryInstruction");
|
||||
var ICAttr = node.Attributes.GetNamedItem("InstructionCount");
|
||||
var IdAttr = node.Attributes.GetNamedItem("Id");
|
||||
if (PIAttr == null) return false;
|
||||
if (IdAttr == null) return false;
|
||||
string Id = IdAttr.InnerText;
|
||||
instDefinition.Id = Id;
|
||||
if (ICAttr != null)
|
||||
{
|
||||
if (int.TryParse(ICAttr.InnerText, out var ic))
|
||||
@@ -171,7 +175,7 @@ namespace SVM.Assembler.Core
|
||||
break;
|
||||
}
|
||||
}
|
||||
definition.InstructionDefinitions.Add(pi, instDefinition);
|
||||
definition.InstructionDefinitions.Add(Id, instDefinition);
|
||||
foreach (var item in instDefinition.Aliases)
|
||||
{
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ namespace SVM.Assembler.Core
|
||||
[Serializable]
|
||||
public class InstructionDefinition
|
||||
{
|
||||
public string Id="";
|
||||
public PrimaryInstruction PrimaryInstruction = PrimaryInstruction.Nop;
|
||||
public int InstructionCount = 1;
|
||||
public List<string> Aliases = new List<string>();
|
||||
|
||||
@@ -4,10 +4,13 @@ using SVM.Assembler.Core.Errors;
|
||||
using SVM.Core;
|
||||
using SVM.Core.Utils;
|
||||
using System;
|
||||
using System.Buffers.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace SVM.Assembler.Core
|
||||
{
|
||||
@@ -78,6 +81,16 @@ namespace SVM.Assembler.Core
|
||||
{
|
||||
return TryParseInt32(realStr, context, out value);
|
||||
}
|
||||
if (context.TryFindLabel(input, out var lblV))
|
||||
{
|
||||
value = lblV;
|
||||
return true;
|
||||
}
|
||||
if (context.TryFindData(input, out var dataV))
|
||||
{
|
||||
value = (int)dataV;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
value = byte.MaxValue;
|
||||
return false;
|
||||
@@ -94,6 +107,42 @@ namespace SVM.Assembler.Core
|
||||
{
|
||||
return TryParseInt64(realStr, context, out value);
|
||||
}
|
||||
if (context.TryFindLabel(input, out var lblV))
|
||||
{
|
||||
value = lblV;
|
||||
return true;
|
||||
}
|
||||
if (context.TryFindData(input, out var dataV))
|
||||
{
|
||||
value = (long)dataV;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
value = byte.MaxValue;
|
||||
return false;
|
||||
}
|
||||
public static bool TryParseUInt64(string input, LinkingContext context, out ulong value)
|
||||
{
|
||||
if (ulong.TryParse(input, out value))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context.IntermediateObject.TryGetConst(input, out var realStr))
|
||||
{
|
||||
return TryParseUInt64(realStr, context, out value);
|
||||
}
|
||||
if (context.TryFindLabel(input, out var lblV))
|
||||
{
|
||||
value = (ulong)lblV;
|
||||
return true;
|
||||
}
|
||||
if (context.TryFindData(input, out var dataV))
|
||||
{
|
||||
value = (ulong)dataV;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
value = byte.MaxValue;
|
||||
return false;
|
||||
@@ -329,21 +378,60 @@ namespace SVM.Assembler.Core
|
||||
uint offset = 0;
|
||||
foreach (var item in Obj.data)
|
||||
{
|
||||
var data = Encoding.UTF8.GetBytes(item.Value);
|
||||
byte[] data2 = new byte[data.Length + sizeof(int)];
|
||||
fixed (byte* ptr = data2)
|
||||
if (item.Value.StartsWith("base64:"))
|
||||
{
|
||||
int len = data.Length;
|
||||
((IntPtr)ptr).SetData(len);
|
||||
var eData = item.Value.Substring("base64:".Length);
|
||||
var data = Convert.FromBase64String(eData);
|
||||
byte[] data2 = new byte[data.Length + sizeof(int)];
|
||||
fixed (byte* ptr = data2)
|
||||
{
|
||||
int len = data.Length;
|
||||
((IntPtr)ptr).SetData(len);
|
||||
}
|
||||
Buffer.BlockCopy(data, 0, data2, sizeof(int), data.Length);
|
||||
context.DataOffsets.Add(item.Key, offset);
|
||||
}
|
||||
else if (item.Value.StartsWith("file:"))
|
||||
{
|
||||
var fileName = item.Value.Substring("file:".Length);
|
||||
var data = File.ReadAllBytes(fileName);
|
||||
byte[] data2 = new byte[data.Length + sizeof(int)];
|
||||
fixed (byte* ptr = data2)
|
||||
{
|
||||
int len = data.Length;
|
||||
((IntPtr)ptr).SetData(len);
|
||||
}
|
||||
Buffer.BlockCopy(data, 0, data2, sizeof(int), data.Length);
|
||||
context.DataOffsets.Add(item.Key, offset);
|
||||
offset += (uint)data2.Length;
|
||||
Data.Add(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte[] data;
|
||||
string str=Regex.Unescape(item.Value);
|
||||
if (str[0] == '\"' && str[^1] == '\"')
|
||||
{
|
||||
data = Encoding.UTF8.GetBytes(str, 1, str.Length - 2);
|
||||
|
||||
}
|
||||
else
|
||||
data = Encoding.UTF8.GetBytes(str);
|
||||
byte[] data2 = new byte[data.Length + sizeof(int)];
|
||||
fixed (byte* ptr = data2)
|
||||
{
|
||||
int len = data.Length;
|
||||
((IntPtr)ptr).SetData(len);
|
||||
}
|
||||
Buffer.BlockCopy(data, 0, data2, sizeof(int), data.Length);
|
||||
context.DataOffsets.Add(item.Key, offset);
|
||||
offset += (uint)data2.Length;
|
||||
Data.Add(data);
|
||||
}
|
||||
Buffer.BlockCopy(data, 0, data2, sizeof(int), data.Length);
|
||||
context.DataOffsets.Add(item.Key, offset);
|
||||
offset += (uint)data2.Length;
|
||||
Data.Add(data);
|
||||
}
|
||||
foreach (var item in Obj.instructions)
|
||||
{
|
||||
if (definition.InstructionDefinitions.TryGetValue(item.inst, out var def))
|
||||
if (definition.InstructionDefinitions.TryGetValue(item.InstDefID, out var def))
|
||||
{
|
||||
|
||||
var instruction = stackalloc SVMInstruction[def.InstructionCount];
|
||||
@@ -362,6 +450,9 @@ namespace SVM.Assembler.Core
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
program.Datas = new byte[offset];
|
||||
int offset2 = 0;
|
||||
|
||||
@@ -16,6 +16,15 @@ namespace SVM.Assembler.Core
|
||||
IntermediateObject = intermediateObject;
|
||||
Definition = definition;
|
||||
}
|
||||
public unsafe bool TryFindData(string label, out uint offset)
|
||||
{
|
||||
if (DataOffsets.TryGetValue(label, out offset))
|
||||
{
|
||||
offset += (uint)IntermediateObject.DetermineFinalInstructionCount(this) * (uint)sizeof(SVMInstruction);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public bool TryFindLabel(string label, out int offset)
|
||||
{
|
||||
label = label + ":";
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<Item Key="sp" Value="2"/>
|
||||
</Registers>
|
||||
<Definitions>
|
||||
<InstructionDefinition PrimaryInstruction="BMath">
|
||||
<InstructionDefinition Id="BMath" PrimaryInstruction="BMath">
|
||||
<Aliases>
|
||||
<Alias Name="bmath"/>
|
||||
<Alias Name="b.math"/>
|
||||
@@ -51,7 +51,7 @@
|
||||
</InstructionParameter>
|
||||
</Parameters>
|
||||
</InstructionDefinition>
|
||||
<InstructionDefinition PrimaryInstruction="SD" InstructionCount="2">
|
||||
<InstructionDefinition Id="std.int32" PrimaryInstruction="SD" InstructionCount="2">
|
||||
<Aliases>
|
||||
<Alias Name="sd.int"/>
|
||||
<Alias Name="sd.int32"/>
|
||||
@@ -73,7 +73,29 @@
|
||||
</InstructionParameter>
|
||||
</Parameters>
|
||||
</InstructionDefinition>
|
||||
<InstructionDefinition PrimaryInstruction="System" InstructionCount="1">
|
||||
<InstructionDefinition Id="sd.int64" PrimaryInstruction="SD" InstructionCount="2">
|
||||
<Aliases>
|
||||
<Alias Name="sd.long"/>
|
||||
<Alias Name="sd.int64"/>
|
||||
</Aliases>
|
||||
<Parameters>
|
||||
<InstructionParameter>
|
||||
<MatchingItems>
|
||||
<Item Id="Word"/>
|
||||
<Item Id="Register"/>
|
||||
</MatchingItems>
|
||||
<ExpectedValue Type="UInt8" Pos="1" Converter="Register" />
|
||||
</InstructionParameter>
|
||||
<InstructionParameter>
|
||||
<MatchingItems>
|
||||
<Item Id="Number"/>
|
||||
<Item Id="Word"/>
|
||||
</MatchingItems>
|
||||
<ExpectedValue Type="Int64" Pos="8" Converter="Integer64" />
|
||||
</InstructionParameter>
|
||||
</Parameters>
|
||||
</InstructionDefinition>
|
||||
<InstructionDefinition Id="syscall" PrimaryInstruction="System" InstructionCount="1">
|
||||
<Aliases>
|
||||
<Alias Name="system"/>
|
||||
<Alias Name="sys"/>
|
||||
|
||||
@@ -15,7 +15,6 @@ namespace SVM.Core
|
||||
public void Init(uint size)
|
||||
{
|
||||
Size = size;
|
||||
Console.WriteLine($"Allocating:{size}");
|
||||
Data = calloc(size);
|
||||
}
|
||||
public T ReadData<T>(int RegisterID) where T : unmanaged
|
||||
|
||||
@@ -37,8 +37,6 @@ namespace SVM.Core
|
||||
{
|
||||
return null;
|
||||
}
|
||||
Console.WriteLine(dataSectionLength);
|
||||
Console.WriteLine(codeCount);
|
||||
IntPtr dataPtr = malloc(dataSectionLength);
|
||||
if (dataSectionLength != 0)
|
||||
{
|
||||
|
||||
@@ -64,7 +64,6 @@ namespace SVM.Core
|
||||
ErrorIDOffset = Config.EIDRegisterID;
|
||||
}
|
||||
var PC = registers.GetData<ulong>((int)PCOffset);
|
||||
Console.WriteLine($"{PC},{Program->InstructionCount}");
|
||||
return PC >= Program->InstructionCount;
|
||||
}
|
||||
|
||||
@@ -85,7 +84,6 @@ namespace SVM.Core
|
||||
var currentInstPtr = GetPointer(PC);
|
||||
var Instruction = currentInstPtr.GetData<SVMInstruction>();
|
||||
var def = Instruction.GetDef();
|
||||
Console.WriteLine(def);
|
||||
fixed (MState* statePtr = &MachineState)
|
||||
{
|
||||
|
||||
@@ -165,7 +163,7 @@ namespace SVM.Core
|
||||
var dataPtr = GetPointer(PC);
|
||||
var data = dataPtr.GetData<int>();
|
||||
registers.SetDataInRegister(Reg, data);
|
||||
Console.WriteLine($"SVM:SD:{data} form PC={PC}");
|
||||
//Console.WriteLine($"SVM:SD:{data} form PC={PC}");
|
||||
}
|
||||
break;
|
||||
case PrimaryInstruction.JAL:
|
||||
@@ -190,7 +188,7 @@ namespace SVM.Core
|
||||
}
|
||||
else
|
||||
{
|
||||
registers.SetData((int)ErrorIDOffset,ErrorIDs.SyscallCallNotExist);
|
||||
registers.SetData((int)ErrorIDOffset, ErrorIDs.SyscallCallNotExist);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -305,12 +303,11 @@ namespace SVM.Core
|
||||
offset1 = Program->DataSize;
|
||||
if (absoluteAddress.offset < offset0)
|
||||
{
|
||||
|
||||
return (IntPtr)(Program->instructions + absoluteAddress.offset / sizeof(SVMInstruction));
|
||||
}
|
||||
else if (absoluteAddress.offset < offset1)
|
||||
else if (absoluteAddress.offset < offset0 + offset1)
|
||||
{
|
||||
return IntPtr.Add((IntPtr)Program->instructions, (int)(absoluteAddress.offset - offset0));
|
||||
return IntPtr.Add((IntPtr)Program->data, (int)(absoluteAddress.offset - offset0));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -358,6 +355,10 @@ namespace SVM.Core
|
||||
{
|
||||
public uint offset;
|
||||
public uint index;
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{index}+{offset}";
|
||||
}
|
||||
}
|
||||
public class SVMConfig
|
||||
{
|
||||
|
||||
@@ -7,9 +7,20 @@ namespace SVM.Core.Utils
|
||||
{
|
||||
public static class StreamUtils
|
||||
{
|
||||
public unsafe static void WriteData(this Stream s, IntPtr ptr, ulong length)
|
||||
{
|
||||
WriteData(s, (byte*)ptr, length);
|
||||
}
|
||||
public unsafe static void WriteData(this Stream s, byte* ptr, ulong length)
|
||||
{
|
||||
for (ulong i = 0; i < length; i++)
|
||||
{
|
||||
s.WriteByte(ptr[i]);
|
||||
}
|
||||
}
|
||||
public unsafe static void WriteData<T>(this Stream s, T data) where T : unmanaged
|
||||
{
|
||||
var ptr=&data;
|
||||
var ptr = &data;
|
||||
Span<byte> buffer = new(ptr, sizeof(T));
|
||||
s.Write(buffer);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user