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;
using SVM.Core.Utils;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
namespace SVM.Advanced.BSDStyleVM namespace SVM.Advanced.BSDStyleVM
@@ -14,7 +16,10 @@ namespace SVM.Advanced.BSDStyleVM
this.baseVM = baseVM; this.baseVM = baseVM;
baseVM.AdditionalData = this; baseVM.AdditionalData = this;
baseVM.Config = BSDConfig.CreateConfig(); baseVM.Config = BSDConfig.CreateConfig();
FDs.Add(0, new FileDescripter(Console.OpenStandardInput()));
FDs.Add(1, new FileDescripter(Console.OpenStandardOutput()));
} }
} }
public class BSDConfig public class BSDConfig
{ {
@@ -30,6 +35,7 @@ namespace SVM.Advanced.BSDStyleVM
public static void SetupSyscall(SVMConfig config) public static void SetupSyscall(SVMConfig config)
{ {
config.FuncCalls.Add(1, BSDStyleFunctions0.__exit); config.FuncCalls.Add(1, BSDStyleFunctions0.__exit);
config.FuncCalls.Add(4, BSDStyleFunctions0.__write);
} }
} }
public static class BSDStyleFunctions0 public static class BSDStyleFunctions0
@@ -37,9 +43,27 @@ namespace SVM.Advanced.BSDStyleVM
public static void __exit(SimpleVirtualMachine machine) public static void __exit(SimpleVirtualMachine machine)
{ {
var status = machine.registers.GetData<int>(10); var status = machine.registers.GetData<int>(10);
Console.WriteLine("Bye-bye!");
Environment.Exit(status); 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 public class FileDescripter
{ {

View File

@@ -17,6 +17,8 @@ Match:
InstMath bmath InstMath bmath
InstSDInt32 sd\.int32 InstSDInt32 sd\.int32
InstSDInt sd\.int InstSDInt sd\.int
InstSDInt64 sd\.int64
InstSDLong sd\.long
InstCvt cvt InstCvt cvt
InstSystem system InstSystem system
InstSys sys InstSys sys
@@ -35,6 +37,8 @@ D \d
Id: Id:
word Word word Word
InstSDInt64 inst
InstSDLong inst
InstMath inst InstMath inst
InstSDInt inst InstSDInt inst
InstSDInt32 inst InstSDInt32 inst
@@ -128,6 +132,7 @@ LabelConstant InternalLbl
operationResult.AddError(new ErrorWMsg($"Unknown Instruction:{LexDef.Content ?? "<null>"}", LexDef)); operationResult.AddError(new ErrorWMsg($"Unknown Instruction:{LexDef.Content ?? "<null>"}", LexDef));
return operationResult; return operationResult;
} }
intermediateInstruction.InstDefID = instructionDef.Id;
intermediateInstruction.inst = instructionDef.PrimaryInstruction; intermediateInstruction.inst = instructionDef.PrimaryInstruction;
foreach (var item in instructionDef.ParameterPattern) 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> data = new Dictionary<string, string>();
public Dictionary<string, string> consts = new Dictionary<string, string>(); public Dictionary<string, string> consts = new Dictionary<string, string>();
public List<IntermediateInstruction> instructions = new List<IntermediateInstruction>(); 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) public bool TryGetConst(string str, out string value)
{ {
return consts.TryGetValue(str, out 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) public bool TryGetLabelPC(string label, out int PC)
{ {
for (int i = 0; i < instructions.Count; i++) for (int i = 0; i < instructions.Count; i++)
@@ -273,6 +294,7 @@ LabelConstant InternalLbl
public class IntermediateInstruction public class IntermediateInstruction
{ {
public LexSegment? Label = null; public LexSegment? Label = null;
public string InstDefID = "";
public PrimaryInstruction inst; public PrimaryInstruction inst;
public List<LexSegment> Parameters = new List<LexSegment>(); 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, byte> RegisterNames = new Dictionary<string, byte>();
public Dictionary<string, Dictionary<string, string>> Enums = new Dictionary<string, Dictionary<string, string>>(); 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] [NonSerialized]
public Dictionary<string, InstructionDefinition> InstructionDefinitionAliases = new Dictionary<string, InstructionDefinition>(); public Dictionary<string, InstructionDefinition> InstructionDefinitionAliases = new Dictionary<string, InstructionDefinition>();
public void Init() public void Init()
@@ -117,7 +117,11 @@ namespace SVM.Assembler.Core
InstructionDefinition instDefinition = new InstructionDefinition(); InstructionDefinition instDefinition = new InstructionDefinition();
var PIAttr = node.Attributes.GetNamedItem("PrimaryInstruction"); var PIAttr = node.Attributes.GetNamedItem("PrimaryInstruction");
var ICAttr = node.Attributes.GetNamedItem("InstructionCount"); var ICAttr = node.Attributes.GetNamedItem("InstructionCount");
var IdAttr = node.Attributes.GetNamedItem("Id");
if (PIAttr == null) return false; if (PIAttr == null) return false;
if (IdAttr == null) return false;
string Id = IdAttr.InnerText;
instDefinition.Id = Id;
if (ICAttr != null) if (ICAttr != null)
{ {
if (int.TryParse(ICAttr.InnerText, out var ic)) if (int.TryParse(ICAttr.InnerText, out var ic))
@@ -171,7 +175,7 @@ namespace SVM.Assembler.Core
break; break;
} }
} }
definition.InstructionDefinitions.Add(pi, instDefinition); definition.InstructionDefinitions.Add(Id, instDefinition);
foreach (var item in instDefinition.Aliases) foreach (var item in instDefinition.Aliases)
{ {

View File

@@ -7,6 +7,7 @@ namespace SVM.Assembler.Core
[Serializable] [Serializable]
public class InstructionDefinition public class InstructionDefinition
{ {
public string Id="";
public PrimaryInstruction PrimaryInstruction = PrimaryInstruction.Nop; public PrimaryInstruction PrimaryInstruction = PrimaryInstruction.Nop;
public int InstructionCount = 1; public int InstructionCount = 1;
public List<string> Aliases = new List<string>(); public List<string> Aliases = new List<string>();

View File

@@ -4,10 +4,13 @@ using SVM.Assembler.Core.Errors;
using SVM.Core; using SVM.Core;
using SVM.Core.Utils; using SVM.Core.Utils;
using System; using System;
using System.Buffers.Text;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.IO;
using System.Reflection.Emit; using System.Reflection.Emit;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
namespace SVM.Assembler.Core namespace SVM.Assembler.Core
{ {
@@ -78,6 +81,16 @@ namespace SVM.Assembler.Core
{ {
return TryParseInt32(realStr, context, out value); 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; value = byte.MaxValue;
return false; return false;
@@ -94,6 +107,42 @@ namespace SVM.Assembler.Core
{ {
return TryParseInt64(realStr, context, out value); 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; value = byte.MaxValue;
return false; return false;
@@ -329,7 +378,23 @@ namespace SVM.Assembler.Core
uint offset = 0; uint offset = 0;
foreach (var item in Obj.data) foreach (var item in Obj.data)
{ {
var data = Encoding.UTF8.GetBytes(item.Value); if (item.Value.StartsWith("base64:"))
{
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)]; byte[] data2 = new byte[data.Length + sizeof(int)];
fixed (byte* ptr = data2) fixed (byte* ptr = data2)
{ {
@@ -341,9 +406,32 @@ namespace SVM.Assembler.Core
offset += (uint)data2.Length; offset += (uint)data2.Length;
Data.Add(data); 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);
}
}
foreach (var item in Obj.instructions) 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]; var instruction = stackalloc SVMInstruction[def.InstructionCount];
@@ -362,6 +450,9 @@ namespace SVM.Assembler.Core
} }
} }
else
{
}
} }
program.Datas = new byte[offset]; program.Datas = new byte[offset];
int offset2 = 0; int offset2 = 0;

View File

@@ -16,6 +16,15 @@ namespace SVM.Assembler.Core
IntermediateObject = intermediateObject; IntermediateObject = intermediateObject;
Definition = definition; 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) public bool TryFindLabel(string label, out int offset)
{ {
label = label + ":"; label = label + ":";

View File

@@ -9,7 +9,7 @@
<Item Key="sp" Value="2"/> <Item Key="sp" Value="2"/>
</Registers> </Registers>
<Definitions> <Definitions>
<InstructionDefinition PrimaryInstruction="BMath"> <InstructionDefinition Id="BMath" PrimaryInstruction="BMath">
<Aliases> <Aliases>
<Alias Name="bmath"/> <Alias Name="bmath"/>
<Alias Name="b.math"/> <Alias Name="b.math"/>
@@ -51,7 +51,7 @@
</InstructionParameter> </InstructionParameter>
</Parameters> </Parameters>
</InstructionDefinition> </InstructionDefinition>
<InstructionDefinition PrimaryInstruction="SD" InstructionCount="2"> <InstructionDefinition Id="std.int32" PrimaryInstruction="SD" InstructionCount="2">
<Aliases> <Aliases>
<Alias Name="sd.int"/> <Alias Name="sd.int"/>
<Alias Name="sd.int32"/> <Alias Name="sd.int32"/>
@@ -73,7 +73,29 @@
</InstructionParameter> </InstructionParameter>
</Parameters> </Parameters>
</InstructionDefinition> </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> <Aliases>
<Alias Name="system"/> <Alias Name="system"/>
<Alias Name="sys"/> <Alias Name="sys"/>

View File

@@ -15,7 +15,6 @@ namespace SVM.Core
public void Init(uint size) public void Init(uint size)
{ {
Size = size; Size = size;
Console.WriteLine($"Allocating:{size}");
Data = calloc(size); Data = calloc(size);
} }
public T ReadData<T>(int RegisterID) where T : unmanaged public T ReadData<T>(int RegisterID) where T : unmanaged

View File

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

View File

@@ -64,7 +64,6 @@ namespace SVM.Core
ErrorIDOffset = Config.EIDRegisterID; ErrorIDOffset = Config.EIDRegisterID;
} }
var PC = registers.GetData<ulong>((int)PCOffset); var PC = registers.GetData<ulong>((int)PCOffset);
Console.WriteLine($"{PC},{Program->InstructionCount}");
return PC >= Program->InstructionCount; return PC >= Program->InstructionCount;
} }
@@ -85,7 +84,6 @@ namespace SVM.Core
var currentInstPtr = GetPointer(PC); var currentInstPtr = GetPointer(PC);
var Instruction = currentInstPtr.GetData<SVMInstruction>(); var Instruction = currentInstPtr.GetData<SVMInstruction>();
var def = Instruction.GetDef(); var def = Instruction.GetDef();
Console.WriteLine(def);
fixed (MState* statePtr = &MachineState) fixed (MState* statePtr = &MachineState)
{ {
@@ -165,7 +163,7 @@ namespace SVM.Core
var dataPtr = GetPointer(PC); var dataPtr = GetPointer(PC);
var data = dataPtr.GetData<int>(); var data = dataPtr.GetData<int>();
registers.SetDataInRegister(Reg, data); registers.SetDataInRegister(Reg, data);
Console.WriteLine($"SVM:SD:{data} form PC={PC}"); //Console.WriteLine($"SVM:SD:{data} form PC={PC}");
} }
break; break;
case PrimaryInstruction.JAL: case PrimaryInstruction.JAL:
@@ -190,7 +188,7 @@ namespace SVM.Core
} }
else else
{ {
registers.SetData((int)ErrorIDOffset,ErrorIDs.SyscallCallNotExist); registers.SetData((int)ErrorIDOffset, ErrorIDs.SyscallCallNotExist);
} }
} }
else else
@@ -305,12 +303,11 @@ namespace SVM.Core
offset1 = Program->DataSize; offset1 = Program->DataSize;
if (absoluteAddress.offset < offset0) if (absoluteAddress.offset < offset0)
{ {
return (IntPtr)(Program->instructions + absoluteAddress.offset / sizeof(SVMInstruction)); 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 offset;
public uint index; public uint index;
public override string ToString()
{
return $"{index}+{offset}";
}
} }
public class SVMConfig public class SVMConfig
{ {

View File

@@ -7,9 +7,20 @@ namespace SVM.Core.Utils
{ {
public static class StreamUtils 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 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)); Span<byte> buffer = new(ptr, sizeof(T));
s.Write(buffer); s.Write(buffer);
} }