2025-07-18 12:43:42 +08:00
|
|
|
|
using SVM.Core.Data;
|
|
|
|
|
|
using SVM.Core.FuncImpl;
|
2025-07-16 20:09:34 +08:00
|
|
|
|
using SVM.Core.Utils;
|
2025-07-18 03:13:41 +08:00
|
|
|
|
using System;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using System.Drawing;
|
|
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
using static SVM.Core.stdc.stdlib;
|
2025-07-16 20:09:34 +08:00
|
|
|
|
namespace SVM.Core
|
|
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Memory Layout:
|
|
|
|
|
|
/// <br/>
|
|
|
|
|
|
/// Index 0 - Program.<br/>
|
|
|
|
|
|
/// Index 1 - GPMemory:<br/>
|
|
|
|
|
|
/// Offset |Length |Usage<br/>
|
|
|
|
|
|
/// 0 |StackLength | Stack
|
|
|
|
|
|
/// </summary>
|
2025-07-16 20:09:34 +08:00
|
|
|
|
public unsafe class SimpleVirtualMachine : IDisposable
|
|
|
|
|
|
{
|
|
|
|
|
|
public Registers registers;
|
|
|
|
|
|
public MemoryBlock Stack;
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public List<MemoryBlock> Memories = new List<MemoryBlock>();
|
2025-07-16 20:09:34 +08:00
|
|
|
|
public SVMConfig? Config = null;
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public MState MachineState;
|
|
|
|
|
|
public SVMProgram* Program = null;
|
|
|
|
|
|
public static uint InitGPMemorySize = 696320;
|
2025-08-01 00:06:32 +10:00
|
|
|
|
public Object? AdditionalData = null;
|
|
|
|
|
|
public ErrorIDs ErrorIDs = new ErrorIDs();
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public void Init(uint StackSize = 1024 * 1024, uint RegisterSize = 512, uint GPMemory = uint.MaxValue)
|
2025-07-16 20:09:34 +08:00
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
registers.Init(RegisterSize);
|
|
|
|
|
|
|
|
|
|
|
|
uint SPOffset = 2;
|
|
|
|
|
|
if (Config != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
SPOffset = Config.SPRegisterID;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (GPMemory == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
if (GPMemory == uint.MaxValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
GPMemory = InitGPMemorySize;
|
|
|
|
|
|
}
|
|
|
|
|
|
MemoryBlock block = new MemoryBlock();
|
|
|
|
|
|
block.Init(GPMemory);
|
|
|
|
|
|
SetMemory(1, block);
|
|
|
|
|
|
registers.SetData<SVMPointer>((int)SPOffset, new SVMPointer() { index = 1, offset = 0 });
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
2025-07-31 02:26:58 +10:00
|
|
|
|
public bool isReachBinaryEnd()
|
|
|
|
|
|
{
|
|
|
|
|
|
uint SPOffset = 2;
|
|
|
|
|
|
uint PCOffset = 1;
|
|
|
|
|
|
uint ErrorIDOffset = 3;
|
|
|
|
|
|
if (Config != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
SPOffset = Config.SPRegisterID;
|
|
|
|
|
|
PCOffset = Config.PCRegisterID;
|
|
|
|
|
|
ErrorIDOffset = Config.EIDRegisterID;
|
|
|
|
|
|
}
|
|
|
|
|
|
var PC = registers.GetData<ulong>((int)PCOffset);
|
|
|
|
|
|
Console.WriteLine($"{PC},{Program->InstructionCount}");
|
|
|
|
|
|
return PC >= Program->InstructionCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-16 20:09:34 +08:00
|
|
|
|
public void Step()
|
|
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
uint SPOffset = 2;
|
|
|
|
|
|
uint PCOffset = 1;
|
|
|
|
|
|
uint ErrorIDOffset = 3;
|
2025-07-16 20:09:34 +08:00
|
|
|
|
if (Config != null)
|
|
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
SPOffset = Config.SPRegisterID;
|
|
|
|
|
|
PCOffset = Config.PCRegisterID;
|
|
|
|
|
|
ErrorIDOffset = Config.EIDRegisterID;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (Program == null) return;
|
|
|
|
|
|
var PC = registers.GetData<ulong>((int)PCOffset);
|
|
|
|
|
|
if (PC >= Program->InstructionCount) return;
|
|
|
|
|
|
var currentInstPtr = GetPointer(PC);
|
|
|
|
|
|
var Instruction = currentInstPtr.GetData<SVMInstruction>();
|
|
|
|
|
|
var def = Instruction.GetDef();
|
2025-07-31 02:26:58 +10:00
|
|
|
|
Console.WriteLine(def);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
fixed (MState* statePtr = &MachineState)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
switch (def)
|
|
|
|
|
|
{
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.BMath:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
var Op = Instruction.GetData<BMathOp>(1);
|
|
|
|
|
|
var NativeType = Instruction.GetData<SVMNativeTypes>(2);
|
|
|
|
|
|
var L = Instruction.GetData<byte>(3);
|
|
|
|
|
|
var R = Instruction.GetData<byte>(4);
|
|
|
|
|
|
var T = Instruction.GetData<byte>(5);
|
|
|
|
|
|
switch (Op)
|
|
|
|
|
|
{
|
|
|
|
|
|
case BMathOp.Add:
|
2025-07-21 01:47:31 +08:00
|
|
|
|
MathImpl.MathAdd(registers, statePtr, NativeType, L, R, T, false);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Sub:
|
2025-07-21 01:47:31 +08:00
|
|
|
|
MathImpl.MathSub(registers, statePtr, NativeType, L, R, T, false);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Mul:
|
2025-07-21 01:47:31 +08:00
|
|
|
|
MathImpl.MathMul(registers, statePtr, NativeType, L, R, T, false);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Div:
|
2025-07-21 01:47:31 +08:00
|
|
|
|
MathImpl.MathDiv(registers, statePtr, NativeType, L, R, T, false);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Mod:
|
|
|
|
|
|
MathImpl.MathMod(registers, statePtr, NativeType, L, R, T);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
case PrimaryInstruction.CBMath:
|
|
|
|
|
|
{
|
|
|
|
|
|
var Op = Instruction.GetData<BMathOp>(1);
|
|
|
|
|
|
var NativeType = Instruction.GetData<SVMNativeTypes>(2);
|
|
|
|
|
|
var L = Instruction.GetData<byte>(3);
|
|
|
|
|
|
var R = Instruction.GetData<byte>(4);
|
|
|
|
|
|
var T = Instruction.GetData<byte>(5);
|
|
|
|
|
|
switch (Op)
|
|
|
|
|
|
{
|
|
|
|
|
|
case BMathOp.Add:
|
|
|
|
|
|
MathImpl.MathAdd(registers, statePtr, NativeType, L, R, T, true);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Sub:
|
|
|
|
|
|
MathImpl.MathSub(registers, statePtr, NativeType, L, R, T, true);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Mul:
|
|
|
|
|
|
MathImpl.MathMul(registers, statePtr, NativeType, L, R, T, true);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Div:
|
|
|
|
|
|
MathImpl.MathDiv(registers, statePtr, NativeType, L, R, T, true);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case BMathOp.Mod:
|
|
|
|
|
|
MathImpl.MathMod(registers, statePtr, NativeType, L, R, T);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.UMath:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.Cvt:
|
2025-07-18 12:43:42 +08:00
|
|
|
|
{
|
|
|
|
|
|
Convert(Instruction);
|
|
|
|
|
|
}
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.Cmp:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.SD:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
{
|
|
|
|
|
|
var Reg = Instruction.GetData<byte>(1);
|
|
|
|
|
|
PC++;
|
|
|
|
|
|
var dataPtr = GetPointer(PC);
|
2025-07-31 02:26:58 +10:00
|
|
|
|
var data = dataPtr.GetData<int>();
|
|
|
|
|
|
registers.SetDataInRegister(Reg, data);
|
|
|
|
|
|
Console.WriteLine($"SVM:SD:{data} form PC={PC}");
|
2025-07-18 03:13:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.JAL:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.JALF:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.Load:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.Save:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.Call:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.Return:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.System:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
if (Config != null)
|
|
|
|
|
|
{
|
2025-08-01 00:06:32 +10:00
|
|
|
|
var target = Instruction.GetData<uint>(4);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
if (Config.FuncCalls.TryGetValue(target, out var func))
|
|
|
|
|
|
{
|
|
|
|
|
|
func(this);
|
|
|
|
|
|
}
|
2025-08-01 00:06:32 +10:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
registers.SetData((int)ErrorIDOffset,ErrorIDs.SyscallCallNotExist);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
registers.SetData((int)ErrorIDOffset, ErrorIDs.SyscallCallNotExist);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
break;
|
2025-07-19 21:41:04 +08:00
|
|
|
|
case PrimaryInstruction.SIMD:
|
2025-07-18 03:13:41 +08:00
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
2025-07-18 03:13:41 +08:00
|
|
|
|
PC++;
|
|
|
|
|
|
registers.SetData<ulong>((int)PCOffset, PC);
|
2025-07-31 02:26:58 +10:00
|
|
|
|
PC = registers.GetData<ulong>((int)PCOffset);
|
2025-07-18 03:13:41 +08:00
|
|
|
|
}
|
2025-07-18 12:43:42 +08:00
|
|
|
|
|
|
|
|
|
|
private void Convert(SVMInstruction Instruction)
|
|
|
|
|
|
{
|
|
|
|
|
|
var SType = Instruction.GetData<SVMNativeTypes>(1);
|
|
|
|
|
|
var TType = Instruction.GetData<SVMNativeTypes>(2);
|
|
|
|
|
|
var L = Instruction.GetData<byte>(3);
|
|
|
|
|
|
var T = Instruction.GetData<byte>(4);
|
|
|
|
|
|
ICastable castable;
|
|
|
|
|
|
switch (SType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case SVMNativeTypes.Int8:
|
|
|
|
|
|
castable = registers.GetData<CompactSByte>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Int16:
|
|
|
|
|
|
castable = registers.GetData<CompactShort>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Int32:
|
|
|
|
|
|
castable = registers.GetData<CompactInt>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Int64:
|
|
|
|
|
|
castable = registers.GetData<CompactLong>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt8:
|
|
|
|
|
|
castable = registers.GetData<CompactByte>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt16:
|
|
|
|
|
|
castable = registers.GetData<CompactUShort>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt32:
|
|
|
|
|
|
castable = registers.GetData<CompactUInt>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt64:
|
|
|
|
|
|
castable = registers.GetData<CompactULong>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Float:
|
|
|
|
|
|
castable = registers.GetData<CompactSingle>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Double:
|
|
|
|
|
|
castable = registers.GetData<CompactDouble>(L);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
switch (TType)
|
|
|
|
|
|
{
|
|
|
|
|
|
case SVMNativeTypes.Int8:
|
|
|
|
|
|
castable.Cast_SByte().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Int16:
|
|
|
|
|
|
castable.Cast_Short().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Int32:
|
|
|
|
|
|
castable.Cast_Int().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Int64:
|
|
|
|
|
|
castable.Cast_Long().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt8:
|
|
|
|
|
|
castable.Cast_Byte().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt16:
|
|
|
|
|
|
castable.Cast_UShort().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt32:
|
|
|
|
|
|
castable.Cast_UInt().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.UInt64:
|
|
|
|
|
|
castable.Cast_ULong().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Float:
|
|
|
|
|
|
castable.Cast_Float().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
case SVMNativeTypes.Double:
|
|
|
|
|
|
castable.Cast_Double().Write(registers.GetPtr(T));
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public IntPtr GetPointer(ulong PC)
|
|
|
|
|
|
{
|
2025-07-31 02:26:58 +10:00
|
|
|
|
return GetPointer(new SVMPointer() { offset = (uint)(PC * (uint)sizeof(SVMInstruction)), index = 0 });
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public IntPtr GetPointer(SVMPointer absoluteAddress)
|
2025-07-16 20:09:34 +08:00
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
if (absoluteAddress.index == 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
ulong offset0 = 0;
|
|
|
|
|
|
ulong offset1 = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (Program != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
offset0 = Program->InstructionCount * (ulong)sizeof(SVMInstruction);
|
|
|
|
|
|
offset1 = Program->DataSize;
|
|
|
|
|
|
if (absoluteAddress.offset < offset0)
|
|
|
|
|
|
{
|
|
|
|
|
|
|
2025-07-31 02:26:58 +10:00
|
|
|
|
return (IntPtr)(Program->instructions + absoluteAddress.offset / sizeof(SVMInstruction));
|
2025-07-18 03:13:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
else if (absoluteAddress.offset < offset1)
|
|
|
|
|
|
{
|
|
|
|
|
|
return IntPtr.Add((IntPtr)Program->instructions, (int)(absoluteAddress.offset - offset0));
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
var realIndex = absoluteAddress.index - 1;
|
|
|
|
|
|
if (realIndex < Memories.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
return IntPtr.Add(Memories[(int)realIndex].StartAddress, (int)absoluteAddress.offset);
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
return IntPtr.Zero;
|
|
|
|
|
|
}
|
|
|
|
|
|
public MemoryBlock SetMemory(int id, MemoryBlock block)
|
|
|
|
|
|
{
|
|
|
|
|
|
var realID = id - 1;
|
|
|
|
|
|
if (id < Memories.Count)
|
|
|
|
|
|
{
|
|
|
|
|
|
var old = Memories[(int)realID];
|
|
|
|
|
|
Memories[(int)realID] = block;
|
|
|
|
|
|
return old;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
var count = realID - Memories.Count;
|
|
|
|
|
|
for (int i = 0; i <= count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
Memories.Add(default);
|
|
|
|
|
|
}
|
|
|
|
|
|
Memories[(int)realID] = block;
|
|
|
|
|
|
return default;
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
|
{
|
|
|
|
|
|
registers.Dispose();
|
|
|
|
|
|
Stack.Dispose();
|
2025-07-18 03:13:41 +08:00
|
|
|
|
foreach (var item in Memories)
|
|
|
|
|
|
{
|
|
|
|
|
|
item.Dispose();
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-18 03:13:41 +08:00
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
|
|
|
public struct SVMPointer
|
|
|
|
|
|
{
|
|
|
|
|
|
public uint offset;
|
|
|
|
|
|
public uint index;
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
public class SVMConfig
|
|
|
|
|
|
{
|
|
|
|
|
|
public Dictionary<uint, FuncCall> FuncCalls = new Dictionary<uint, FuncCall>();
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public uint SPRegisterID;
|
|
|
|
|
|
public uint PCRegisterID;
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Error ID Register.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
public uint EIDRegisterID;
|
|
|
|
|
|
}
|
2025-08-01 00:06:32 +10:00
|
|
|
|
public class ErrorIDs
|
|
|
|
|
|
{
|
|
|
|
|
|
public int SyscallCallNotExist = 1;
|
|
|
|
|
|
public int MAX_ERROR_ID = short.MaxValue;
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
public delegate void FuncCall(SimpleVirtualMachine machine);
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
|
|
|
public struct MState
|
|
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public byte OF;
|
2025-07-18 12:43:42 +08:00
|
|
|
|
public byte CF;
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
|
|
|
public struct MemoryBlock : IDisposable
|
|
|
|
|
|
{
|
|
|
|
|
|
public IntPtr StartAddress;
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public uint Size;
|
|
|
|
|
|
public void Init(uint Size)
|
|
|
|
|
|
{
|
|
|
|
|
|
this.Size = Size;
|
|
|
|
|
|
StartAddress = malloc(Size);
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
public void Dispose()
|
|
|
|
|
|
{
|
|
|
|
|
|
free(StartAddress);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public struct Callframe
|
2025-07-16 20:09:34 +08:00
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
public ulong PC;
|
|
|
|
|
|
public ulong SP;
|
|
|
|
|
|
}
|
|
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
|
|
|
|
public unsafe struct SVMInstruction
|
|
|
|
|
|
{
|
|
|
|
|
|
public ulong data;
|
|
|
|
|
|
public T GetData<T>(int offset) where T : unmanaged
|
2025-07-16 20:09:34 +08:00
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
fixed (ulong* dataPtr = &data)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ((T*)(((byte*)dataPtr) + offset))[0];
|
|
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
2025-07-19 21:41:04 +08:00
|
|
|
|
public PrimaryInstruction GetDef()
|
2025-07-16 20:09:34 +08:00
|
|
|
|
{
|
2025-07-18 03:13:41 +08:00
|
|
|
|
fixed (ulong* dataPtr = &data)
|
|
|
|
|
|
{
|
2025-07-19 21:41:04 +08:00
|
|
|
|
return ((PrimaryInstruction*)dataPtr)[0];
|
2025-07-18 03:13:41 +08:00
|
|
|
|
}
|
2025-07-16 20:09:34 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|