diff --git a/src/SVM.Core/FuncImpl/CompareFunctions.cs b/src/SVM.Core/FuncImpl/CompareFunctions.cs new file mode 100644 index 0000000..5a3750d --- /dev/null +++ b/src/SVM.Core/FuncImpl/CompareFunctions.cs @@ -0,0 +1,309 @@ +using SVM.Core.Data; +using System.Runtime.CompilerServices; + +namespace SVM.Core.FuncImpl +{ + public unsafe static class CompareFunctions + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void LT(Registers context, SVMInstruction_InSeparateBytes inst) + { + var type = (NativeType)inst.D2; + var L = inst.D3; + var R = inst.D4; + var T = inst.D4; + + switch (type) + { + case NativeType.BU: + GenericLT(context, L, R, T); + break; + case NativeType.BS: + GenericLT(context, L, R, T); + break; + case NativeType.S: + GenericLT(context, L, R, T); + break; + case NativeType.SU: + GenericLT(context, L, R, T); + break; + case NativeType.I: + GenericLT(context, L, R, T); + break; + case NativeType.IU: + GenericLT(context, L, R, T); + break; + case NativeType.L: + GenericLT(context, L, R, T); + break; + case NativeType.LU: + GenericLT(context, L, R, T); + break; + case NativeType.F: + GenericLT(context, L, R, T); + break; + case NativeType.D: + GenericLT(context, L, R, T); + break; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GT(Registers context, SVMInstruction_InSeparateBytes inst) + { + var type = (NativeType)inst.D2; + var L = inst.D3; + var R = inst.D4; + var T = inst.D4; + + switch (type) + { + case NativeType.BU: + GenericGT(context, L, R, T); + break; + case NativeType.BS: + GenericGT(context, L, R, T); + break; + case NativeType.S: + GenericGT(context, L, R, T); + break; + case NativeType.SU: + GenericGT(context, L, R, T); + break; + case NativeType.I: + GenericGT(context, L, R, T); + break; + case NativeType.IU: + GenericGT(context, L, R, T); + break; + case NativeType.L: + GenericGT(context, L, R, T); + break; + case NativeType.LU: + GenericGT(context, L, R, T); + break; + case NativeType.F: + GenericGT(context, L, R, T); + break; + case NativeType.D: + GenericGT(context, L, R, T); + break; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void LE(Registers context, SVMInstruction_InSeparateBytes inst) + { + var type = (NativeType)inst.D2; + var L = inst.D3; + var R = inst.D4; + var T = inst.D4; + + switch (type) + { + case NativeType.BU: + GenericLT(context, L, R, T); + break; + case NativeType.BS: + GenericLT(context, L, R, T); + break; + case NativeType.S: + GenericLT(context, L, R, T); + break; + case NativeType.SU: + GenericLT(context, L, R, T); + break; + case NativeType.I: + GenericLT(context, L, R, T); + break; + case NativeType.IU: + GenericLT(context, L, R, T); + break; + case NativeType.L: + GenericLT(context, L, R, T); + break; + case NativeType.LU: + GenericLT(context, L, R, T); + break; + case NativeType.F: + GenericLT(context, L, R, T); + break; + case NativeType.D: + GenericLT(context, L, R, T); + break; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GE(Registers context, SVMInstruction_InSeparateBytes inst) + { + var type = (NativeType)inst.D2; + var L = inst.D3; + var R = inst.D4; + var T = inst.D4; + + switch (type) + { + case NativeType.BU: + GenericGE(context, L, R, T); + break; + case NativeType.BS: + GenericGE(context, L, R, T); + break; + case NativeType.S: + GenericGE(context, L, R, T); + break; + case NativeType.SU: + GenericGE(context, L, R, T); + break; + case NativeType.I: + GenericGE(context, L, R, T); + break; + case NativeType.IU: + GenericGE(context, L, R, T); + break; + case NativeType.L: + GenericGE(context, L, R, T); + break; + case NativeType.LU: + GenericGE(context, L, R, T); + break; + case NativeType.F: + GenericGE(context, L, R, T); + break; + case NativeType.D: + GenericGE(context, L, R, T); + break; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void EQ(Registers context, SVMInstruction_InSeparateBytes inst) + { + var type = (NativeType)inst.D2; + var L = inst.D3; + var R = inst.D4; + var T = inst.D4; + + switch (type) + { + case NativeType.BU: + GenericEQ(context, L, R, T); + break; + case NativeType.BS: + GenericEQ(context, L, R, T); + break; + case NativeType.S: + GenericEQ(context, L, R, T); + break; + case NativeType.SU: + GenericEQ(context, L, R, T); + break; + case NativeType.I: + GenericEQ(context, L, R, T); + break; + case NativeType.IU: + GenericEQ(context, L, R, T); + break; + case NativeType.L: + GenericEQ(context, L, R, T); + break; + case NativeType.LU: + GenericEQ(context, L, R, T); + break; + case NativeType.F: + GenericEQ(context, L, R, T); + break; + case NativeType.D: + GenericEQ(context, L, R, T); + break; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void NE(Registers context, SVMInstruction_InSeparateBytes inst) + { + var type = (NativeType)inst.D2; + var L = inst.D3; + var R = inst.D4; + var T = inst.D4; + + switch (type) + { + case NativeType.BU: + GenericNE(context, L, R, T); + break; + case NativeType.BS: + GenericNE(context, L, R, T); + break; + case NativeType.S: + GenericNE(context, L, R, T); + break; + case NativeType.SU: + GenericNE(context, L, R, T); + break; + case NativeType.I: + GenericNE(context, L, R, T); + break; + case NativeType.IU: + GenericNE(context, L, R, T); + break; + case NativeType.L: + GenericNE(context, L, R, T); + break; + case NativeType.LU: + GenericNE(context, L, R, T); + break; + case NativeType.F: + GenericNE(context, L, R, T); + break; + case NativeType.D: + GenericNE(context, L, R, T); + break; + } + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GenericLT(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData + { + var LN = Register.GetData(L); + var RN = Register.GetData(R); + bool TN = LN.LT(RN); + Register.SetData(T, TN ? 1 : 0); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GenericGT(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData + { + var LN = Register.GetData(L); + var RN = Register.GetData(R); + bool TN = LN.GT(RN); + Register.SetData(T, TN ? 1 : 0); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GenericLE(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData + { + var LN = Register.GetData(L); + var RN = Register.GetData(R); + bool TN = LN.LE(RN); + Register.SetData(T, TN ? 1 : 0); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GenericGE(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData + { + var LN = Register.GetData(L); + var RN = Register.GetData(R); + bool TN = LN.GE(RN); + Register.SetData(T, TN ? 1 : 0); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GenericEQ(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData + { + var LN = Register.GetData(L); + var RN = Register.GetData(R); + bool TN = LN.EQ(RN); + Register.SetData(T, TN ? 1 : 0); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void GenericNE(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData + { + var LN = Register.GetData(L); + var RN = Register.GetData(R); + bool TN = LN.NE(RN); + Register.SetData(T, TN ? 1 : 0); + } + } +} diff --git a/src/SVM.Core/PrimaryInstruction.cs b/src/SVM.Core/PrimaryInstruction.cs index 41fb60b..d56adc9 100644 --- a/src/SVM.Core/PrimaryInstruction.cs +++ b/src/SVM.Core/PrimaryInstruction.cs @@ -17,8 +17,8 @@ //Cvt [I]SType [I]TType [I]S [I]T Cvt, // Set Conditional Register to 1 if condition met. - // 0 1 2 3 4 - // Cmp [R]Op [R]L [R]R [R]T + // 0 1 2 3 4 5 + // Cmp [R]Op [I]Type [R]L [R]R [R]T Cmp, //Set Data to Register //SD T @@ -75,6 +75,21 @@ Float, Double, } + + public enum NativeType : byte + { + BS = SVMNativeTypes.Int8, + BU = SVMNativeTypes.UInt8, + S = SVMNativeTypes.Int16, + SU = SVMNativeTypes.UInt16, + I = SVMNativeTypes.Int32, + IU = SVMNativeTypes.UInt32, + L = SVMNativeTypes.Int64, + LU = SVMNativeTypes.UInt64, + F = SVMNativeTypes.Float, + D = SVMNativeTypes.Double, + R + } public enum ConditionFlag : byte { /// @@ -109,4 +124,8 @@ Log, Sqrt } + public enum CompareOperator : byte + { + LT = 0, GT = 1, GE = 2, EQ = 3, LE = 4, NE = 5, + } } diff --git a/src/SVM.Core/SimpleVirtualMachine.cs b/src/SVM.Core/SimpleVirtualMachine.cs index bcbaf5d..cf257f6 100644 --- a/src/SVM.Core/SimpleVirtualMachine.cs +++ b/src/SVM.Core/SimpleVirtualMachine.cs @@ -215,6 +215,34 @@ namespace SVM.Core } break; case PrimaryInstruction.Cmp: + { + var InstAlt = Instruction.CastAs(0); + var OP = (CompareOperator)InstAlt.D0; + switch (OP) + { + case CompareOperator.LT: + CompareFunctions.LT(this.registers, InstAlt); + break; + case CompareOperator.GT: + CompareFunctions.GT(this.registers, InstAlt); + break; + case CompareOperator.GE: + CompareFunctions.GE(this.registers, InstAlt); + break; + case CompareOperator.EQ: + CompareFunctions.EQ(this.registers, InstAlt); + break; + case CompareOperator.LE: + CompareFunctions.LE(this.registers, InstAlt); + break; + case CompareOperator.NE: + CompareFunctions.NE(this.registers, InstAlt); + break; + default: + break; + } + + } break; case PrimaryInstruction.SD: { @@ -550,4 +578,16 @@ namespace SVM.Core } } } + [StructLayout(LayoutKind.Sequential)] + public unsafe struct SVMInstruction_InSeparateBytes + { + public byte D0; + public byte D1; + public byte D2; + public byte D3; + public byte D4; + public byte D5; + public byte D6; + public byte D7; + } } diff --git a/src/SVM.Core/Utils/PointerUtils.cs b/src/SVM.Core/Utils/PointerUtils.cs index d9e274f..bd66e80 100644 --- a/src/SVM.Core/Utils/PointerUtils.cs +++ b/src/SVM.Core/Utils/PointerUtils.cs @@ -41,6 +41,10 @@ namespace SVM.Core.Utils { GetDataWithOffsetInStructCount(ptr, (IntPtr)dest, offset); } + public static V CastAs(this T t, ushort offset = 0) where T : unmanaged where V : unmanaged + { + return ((V*)&t)[offset]; + } public static void SetData(this IntPtr ptr, T data) where T : unmanaged { var srcPtr = (byte*)&data;