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:
2025-08-01 03:43:09 +10:00
parent 269a2b51be
commit 6eb87e433e
11 changed files with 210 additions and 28 deletions

View File

@@ -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
{

View File

@@ -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>();
}

View File

@@ -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)
{

View File

@@ -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>();

View File

@@ -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;

View File

@@ -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 + ":";

View File

@@ -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"/>

View File

@@ -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

View File

@@ -37,8 +37,6 @@ namespace SVM.Core
{
return null;
}
Console.WriteLine(dataSectionLength);
Console.WriteLine(codeCount);
IntPtr dataPtr = malloc(dataSectionLength);
if (dataSectionLength != 0)
{

View File

@@ -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
{

View File

@@ -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);
}