From 6eb87e433e889f0552a4acfb5be860107bda0c69 Mon Sep 17 00:00:00 2001 From: Creeper Lv Date: Fri, 1 Aug 2025 03:43:09 +1000 Subject: [PATCH] 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 --- src/SVM.Advanced/BSDStyleVM/BSDLikeWrapper.cs | 26 +++- src/SVM.Assembler.Core/Assembler.cs | 24 +++- src/SVM.Assembler.Core/ISADefinition.cs | 8 +- .../InstructionDefinition.cs | 1 + src/SVM.Assembler.Core/Linker.cs | 111 ++++++++++++++++-- src/SVM.Assembler.Core/LinkingContext.cs | 9 ++ src/SVM.Assembler/ISA.xml | 28 ++++- src/SVM.Core/Registers.cs | 1 - src/SVM.Core/SVMProgram.cs | 2 - src/SVM.Core/SimpleVirtualMachine.cs | 15 +-- src/SVM.Core/Utils/StreamUtils.cs | 13 +- 11 files changed, 210 insertions(+), 28 deletions(-) diff --git a/src/SVM.Advanced/BSDStyleVM/BSDLikeWrapper.cs b/src/SVM.Advanced/BSDStyleVM/BSDLikeWrapper.cs index f9af9da..badb0ef 100644 --- a/src/SVM.Advanced/BSDStyleVM/BSDLikeWrapper.cs +++ b/src/SVM.Advanced/BSDStyleVM/BSDLikeWrapper.cs @@ -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(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(10); + var ptr = machine.registers.GetData(11); + var size = machine.registers.GetData(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 { diff --git a/src/SVM.Assembler.Core/Assembler.cs b/src/SVM.Assembler.Core/Assembler.cs index 4743e89..d8be97c 100644 --- a/src/SVM.Assembler.Core/Assembler.cs +++ b/src/SVM.Assembler.Core/Assembler.cs @@ -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 ?? ""}", 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 data = new Dictionary(); public Dictionary consts = new Dictionary(); public List instructions = new List(); + 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 Parameters = new List(); } diff --git a/src/SVM.Assembler.Core/ISADefinition.cs b/src/SVM.Assembler.Core/ISADefinition.cs index f4beeaf..773997f 100644 --- a/src/SVM.Assembler.Core/ISADefinition.cs +++ b/src/SVM.Assembler.Core/ISADefinition.cs @@ -15,7 +15,7 @@ namespace SVM.Assembler.Core { public Dictionary RegisterNames = new Dictionary(); public Dictionary> Enums = new Dictionary>(); - public Dictionary InstructionDefinitions = new Dictionary(); + public Dictionary InstructionDefinitions = new Dictionary(); [NonSerialized] public Dictionary InstructionDefinitionAliases = new Dictionary(); 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) { diff --git a/src/SVM.Assembler.Core/InstructionDefinition.cs b/src/SVM.Assembler.Core/InstructionDefinition.cs index fb7d43c..673ef58 100644 --- a/src/SVM.Assembler.Core/InstructionDefinition.cs +++ b/src/SVM.Assembler.Core/InstructionDefinition.cs @@ -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 Aliases = new List(); diff --git a/src/SVM.Assembler.Core/Linker.cs b/src/SVM.Assembler.Core/Linker.cs index 1c0bf99..0f1ed5b 100644 --- a/src/SVM.Assembler.Core/Linker.cs +++ b/src/SVM.Assembler.Core/Linker.cs @@ -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; diff --git a/src/SVM.Assembler.Core/LinkingContext.cs b/src/SVM.Assembler.Core/LinkingContext.cs index 03edac0..54a4d60 100644 --- a/src/SVM.Assembler.Core/LinkingContext.cs +++ b/src/SVM.Assembler.Core/LinkingContext.cs @@ -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 + ":"; diff --git a/src/SVM.Assembler/ISA.xml b/src/SVM.Assembler/ISA.xml index ff1f6ff..746d481 100644 --- a/src/SVM.Assembler/ISA.xml +++ b/src/SVM.Assembler/ISA.xml @@ -9,7 +9,7 @@ - + @@ -51,7 +51,7 @@ - + @@ -73,7 +73,29 @@ - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SVM.Core/Registers.cs b/src/SVM.Core/Registers.cs index d5c565b..10bc430 100644 --- a/src/SVM.Core/Registers.cs +++ b/src/SVM.Core/Registers.cs @@ -15,7 +15,6 @@ namespace SVM.Core public void Init(uint size) { Size = size; - Console.WriteLine($"Allocating:{size}"); Data = calloc(size); } public T ReadData(int RegisterID) where T : unmanaged diff --git a/src/SVM.Core/SVMProgram.cs b/src/SVM.Core/SVMProgram.cs index 76add88..cf42674 100644 --- a/src/SVM.Core/SVMProgram.cs +++ b/src/SVM.Core/SVMProgram.cs @@ -37,8 +37,6 @@ namespace SVM.Core { return null; } - Console.WriteLine(dataSectionLength); - Console.WriteLine(codeCount); IntPtr dataPtr = malloc(dataSectionLength); if (dataSectionLength != 0) { diff --git a/src/SVM.Core/SimpleVirtualMachine.cs b/src/SVM.Core/SimpleVirtualMachine.cs index 336597d..0300462 100644 --- a/src/SVM.Core/SimpleVirtualMachine.cs +++ b/src/SVM.Core/SimpleVirtualMachine.cs @@ -64,7 +64,6 @@ namespace SVM.Core ErrorIDOffset = Config.EIDRegisterID; } var PC = registers.GetData((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(); 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(); 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 { diff --git a/src/SVM.Core/Utils/StreamUtils.cs b/src/SVM.Core/Utils/StreamUtils.cs index 4bcded3..e374ed2 100644 --- a/src/SVM.Core/Utils/StreamUtils.cs +++ b/src/SVM.Core/Utils/StreamUtils.cs @@ -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(this Stream s, T data) where T : unmanaged { - var ptr=&data; + var ptr = &data; Span buffer = new(ptr, sizeof(T)); s.Write(buffer); }