Implemented CMP.

This commit is contained in:
2025-08-26 23:51:58 +10:00
parent 7e57c4ded6
commit f62e96494d
4 changed files with 374 additions and 2 deletions

View File

@@ -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<CompactByte>(context, L, R, T);
break;
case NativeType.BS:
GenericLT<CompactSByte>(context, L, R, T);
break;
case NativeType.S:
GenericLT<CompactShort>(context, L, R, T);
break;
case NativeType.SU:
GenericLT<CompactUShort>(context, L, R, T);
break;
case NativeType.I:
GenericLT<CompactInt>(context, L, R, T);
break;
case NativeType.IU:
GenericLT<CompactUInt>(context, L, R, T);
break;
case NativeType.L:
GenericLT<CompactLong>(context, L, R, T);
break;
case NativeType.LU:
GenericLT<CompactULong>(context, L, R, T);
break;
case NativeType.F:
GenericLT<CompactSingle>(context, L, R, T);
break;
case NativeType.D:
GenericLT<CompactDouble>(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<CompactByte>(context, L, R, T);
break;
case NativeType.BS:
GenericGT<CompactSByte>(context, L, R, T);
break;
case NativeType.S:
GenericGT<CompactShort>(context, L, R, T);
break;
case NativeType.SU:
GenericGT<CompactUShort>(context, L, R, T);
break;
case NativeType.I:
GenericGT<CompactInt>(context, L, R, T);
break;
case NativeType.IU:
GenericGT<CompactUInt>(context, L, R, T);
break;
case NativeType.L:
GenericGT<CompactLong>(context, L, R, T);
break;
case NativeType.LU:
GenericGT<CompactULong>(context, L, R, T);
break;
case NativeType.F:
GenericGT<CompactSingle>(context, L, R, T);
break;
case NativeType.D:
GenericGT<CompactDouble>(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<CompactByte>(context, L, R, T);
break;
case NativeType.BS:
GenericLT<CompactSByte>(context, L, R, T);
break;
case NativeType.S:
GenericLT<CompactShort>(context, L, R, T);
break;
case NativeType.SU:
GenericLT<CompactUShort>(context, L, R, T);
break;
case NativeType.I:
GenericLT<CompactInt>(context, L, R, T);
break;
case NativeType.IU:
GenericLT<CompactUInt>(context, L, R, T);
break;
case NativeType.L:
GenericLT<CompactLong>(context, L, R, T);
break;
case NativeType.LU:
GenericLT<CompactULong>(context, L, R, T);
break;
case NativeType.F:
GenericLT<CompactSingle>(context, L, R, T);
break;
case NativeType.D:
GenericLT<CompactDouble>(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<CompactByte>(context, L, R, T);
break;
case NativeType.BS:
GenericGE<CompactSByte>(context, L, R, T);
break;
case NativeType.S:
GenericGE<CompactShort>(context, L, R, T);
break;
case NativeType.SU:
GenericGE<CompactUShort>(context, L, R, T);
break;
case NativeType.I:
GenericGE<CompactInt>(context, L, R, T);
break;
case NativeType.IU:
GenericGE<CompactUInt>(context, L, R, T);
break;
case NativeType.L:
GenericGE<CompactLong>(context, L, R, T);
break;
case NativeType.LU:
GenericGE<CompactULong>(context, L, R, T);
break;
case NativeType.F:
GenericGE<CompactSingle>(context, L, R, T);
break;
case NativeType.D:
GenericGE<CompactDouble>(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<CompactByte>(context, L, R, T);
break;
case NativeType.BS:
GenericEQ<CompactSByte>(context, L, R, T);
break;
case NativeType.S:
GenericEQ<CompactShort>(context, L, R, T);
break;
case NativeType.SU:
GenericEQ<CompactUShort>(context, L, R, T);
break;
case NativeType.I:
GenericEQ<CompactInt>(context, L, R, T);
break;
case NativeType.IU:
GenericEQ<CompactUInt>(context, L, R, T);
break;
case NativeType.L:
GenericEQ<CompactLong>(context, L, R, T);
break;
case NativeType.LU:
GenericEQ<CompactULong>(context, L, R, T);
break;
case NativeType.F:
GenericEQ<CompactSingle>(context, L, R, T);
break;
case NativeType.D:
GenericEQ<CompactDouble>(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<CompactByte>(context, L, R, T);
break;
case NativeType.BS:
GenericNE<CompactSByte>(context, L, R, T);
break;
case NativeType.S:
GenericNE<CompactShort>(context, L, R, T);
break;
case NativeType.SU:
GenericNE<CompactUShort>(context, L, R, T);
break;
case NativeType.I:
GenericNE<CompactInt>(context, L, R, T);
break;
case NativeType.IU:
GenericNE<CompactUInt>(context, L, R, T);
break;
case NativeType.L:
GenericNE<CompactLong>(context, L, R, T);
break;
case NativeType.LU:
GenericNE<CompactULong>(context, L, R, T);
break;
case NativeType.F:
GenericNE<CompactSingle>(context, L, R, T);
break;
case NativeType.D:
GenericNE<CompactDouble>(context, L, R, T);
break;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GenericLT<N>(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData<N>
{
var LN = Register.GetData<N>(L);
var RN = Register.GetData<N>(R);
bool TN = LN.LT(RN);
Register.SetData(T, TN ? 1 : 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GenericGT<N>(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData<N>
{
var LN = Register.GetData<N>(L);
var RN = Register.GetData<N>(R);
bool TN = LN.GT(RN);
Register.SetData(T, TN ? 1 : 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GenericLE<N>(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData<N>
{
var LN = Register.GetData<N>(L);
var RN = Register.GetData<N>(R);
bool TN = LN.LE(RN);
Register.SetData(T, TN ? 1 : 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GenericGE<N>(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData<N>
{
var LN = Register.GetData<N>(L);
var RN = Register.GetData<N>(R);
bool TN = LN.GE(RN);
Register.SetData(T, TN ? 1 : 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GenericEQ<N>(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData<N>
{
var LN = Register.GetData<N>(L);
var RN = Register.GetData<N>(R);
bool TN = LN.EQ(RN);
Register.SetData(T, TN ? 1 : 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void GenericNE<N>(Registers Register, int L, int R, int T) where N : unmanaged, INumbericData<N>
{
var LN = Register.GetData<N>(L);
var RN = Register.GetData<N>(R);
bool TN = LN.NE(RN);
Register.SetData(T, TN ? 1 : 0);
}
}
}

View File

@@ -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
{
/// <summary>
@@ -109,4 +124,8 @@
Log,
Sqrt
}
public enum CompareOperator : byte
{
LT = 0, GT = 1, GE = 2, EQ = 3, LE = 4, NE = 5,
}
}

View File

@@ -215,6 +215,34 @@ namespace SVM.Core
}
break;
case PrimaryInstruction.Cmp:
{
var InstAlt = Instruction.CastAs<SVMInstruction, SVMInstruction_InSeparateBytes>(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;
}
}

View File

@@ -41,6 +41,10 @@ namespace SVM.Core.Utils
{
GetDataWithOffsetInStructCount<T>(ptr, (IntPtr)dest, offset);
}
public static V CastAs<T, V>(this T t, ushort offset = 0) where T : unmanaged where V : unmanaged
{
return ((V*)&t)[offset];
}
public static void SetData<T>(this IntPtr ptr, T data) where T : unmanaged
{
var srcPtr = (byte*)&data;