using System;
using System.Collections.Generic;
using System.Text;
using num = System.Single;
namespace Twiggery
{
public partial class TVM
{
/// <summary>
/// Base class of ASM instructions
/// </summary>
public abstract class Asm
{
#region Variables
protected byte opcode = 0;
/// <summary>
/// Opcode
/// </summary>
public byte Opcode
{
get { return opcode; }
}
protected num[] operand = null;
/// <summary>
/// Operand
/// </summary>
public num[] Operand
{
get { return operand; }
}
#endregion
#region Assist
/// <summary>
/// Byte code to Type
/// </summary>
public static Dictionary<byte, Type> BYTE_TYPE = null;
/// <summary>
/// Type to Byte code
/// </summary>
public static Dictionary<Type, byte> TYPE_BYTE = null;
/// <summary>
/// Initialize ASM instruction system
/// </summary>
public static void Initialize()
{
BYTE_TYPE = new Dictionary<byte, Type>();
TYPE_BYTE = new Dictionary<Type, byte>();
#region Memory operation instruction
BYTE_TYPE.Add(127, typeof(MOV));
TYPE_BYTE.Add(typeof(MOV), 127);
BYTE_TYPE.Add(126, typeof(LAM));
TYPE_BYTE.Add(typeof(LAM), 126);
#endregion
#region Numeric calculation instruction
BYTE_TYPE.Add(119, typeof(ADD));
TYPE_BYTE.Add(typeof(ADD), 119);
BYTE_TYPE.Add(118, typeof(SUB));
TYPE_BYTE.Add(typeof(SUB), 118);
BYTE_TYPE.Add(117, typeof(MUL));
TYPE_BYTE.Add(typeof(MUL), 117);
BYTE_TYPE.Add(116, typeof(DIV));
TYPE_BYTE.Add(typeof(DIV), 116);
BYTE_TYPE.Add(115, typeof(MOD));
TYPE_BYTE.Add(typeof(MOD), 115);
#endregion
#region Numeric comparison instruction
BYTE_TYPE.Add(109, typeof(CE));
TYPE_BYTE.Add(typeof(CE), 109);
BYTE_TYPE.Add(108, typeof(CLE));
TYPE_BYTE.Add(typeof(CLE), 108);
BYTE_TYPE.Add(107, typeof(CGE));
TYPE_BYTE.Add(typeof(CGE), 107);
BYTE_TYPE.Add(106, typeof(CL));
TYPE_BYTE.Add(typeof(CL), 106);
BYTE_TYPE.Add(105, typeof(CG));
TYPE_BYTE.Add(typeof(CG), 105);
BYTE_TYPE.Add(104, typeof(CNE));
TYPE_BYTE.Add(typeof(CNE), 104);
#endregion
#region Boolean operation instruction
BYTE_TYPE.Add(99, typeof(AND));
TYPE_BYTE.Add(typeof(AND), 99);
BYTE_TYPE.Add(98, typeof(OR));
TYPE_BYTE.Add(typeof(OR), 98);
BYTE_TYPE.Add(97, typeof(NOT));
TYPE_BYTE.Add(typeof(NOT), 97);
#endregion
#region Instruction jump
BYTE_TYPE.Add(10, typeof(JMP));
TYPE_BYTE.Add(typeof(JMP), 10);
BYTE_TYPE.Add(11, typeof(JF));
TYPE_BYTE.Add(typeof(JF), 11);
BYTE_TYPE.Add(12, typeof(JT));
TYPE_BYTE.Add(typeof(JT), 12);
#endregion
#region Other special instruction
BYTE_TYPE.Add(0, typeof(HLT));
TYPE_BYTE.Add(typeof(HLT), 0);
BYTE_TYPE.Add(1, typeof(CALL));
TYPE_BYTE.Add(typeof(CALL), 1);
BYTE_TYPE.Add(2, typeof(ARG));
TYPE_BYTE.Add(typeof(ARG), 2);
BYTE_TYPE.Add(3, typeof(HAL));
TYPE_BYTE.Add(typeof(HAL), 3);
#endregion
}
/// <summary>
/// Convert from int to byte[]
/// </summary>
/// <param name="arg">num</param>
/// <returns>byte[]</returns>
protected static byte[] parseNumberToBytes(num arg)
{
byte[] buffer = BitConverter.GetBytes(arg);
return buffer;
}
/// <summary>
/// Conver byte[] to int
/// </summary>
/// <param name="arg">byte[]</param>
/// <returns>num</returns>
protected static num parseBytesToNumber(byte[] arg)
{
if (typeof(num) == typeof(float))
{
return BitConverter.ToSingle(arg, 0);
}
else if (typeof(num) == typeof(int))
{
return BitConverter.ToInt32(arg, 0);
}
return num.MinValue;
}
#endregion
#region Analyze
/// <summary>
/// Convert ASM instruction into bytecode
/// </summary>
/// <param name="asmOp">ASM instruction</param>
/// <param name="bytes">Bytecode buffer</param>
public static void ToBytes(Asm asm, ref List<byte> bytes)
{
num op1 = asm.operand.Length >= 1 ? asm.operand[0] : 0;
num op2 = asm.operand.Length >= 2 ? asm.operand[1] : 0;
byte[] bBuffer1 = parseNumberToBytes(op1);
byte[] bBuffer2 = parseNumberToBytes(op2);
bytes.Add(asm.opcode);
for (int i = 0; i < 4; i++)
bytes.Add(bBuffer1[i]);
for (int i = 0; i < 4; i++)
bytes.Add(bBuffer2[i]);
}
/// <summary>
/// Convert bytecode into ASM instruction
/// </summary>
/// <param name="bytes">Bytecode buffer</param>
/// <returns>ASM instruction</returns>
public static Asm FromBytes(ref List<byte> bytes)
{
byte op = bytes[0];
bytes.RemoveAt(0);
byte[] bOp1 ={ bytes[0], bytes[1], bytes[2], bytes[3] };
bytes.RemoveRange(0, 4);
byte[] bOp2 ={ bytes[0], bytes[1], bytes[2], bytes[3] };
bytes.RemoveRange(0, 4);
num op1 = parseBytesToNumber(bOp1);
num op2 = parseBytesToNumber(bOp2);
Type t = BYTE_TYPE[op];
Asm asm = (Asm)Activator.CreateInstance(t);
if (asm.operand.Length >= 1)
asm.operand[0] = op1;
if (asm.operand.Length >= 2)
asm.operand[1] = op2;
return asm;
}
#endregion
}
#region Memory operation instruction
/// <summary>
/// Copy data
/// </summary>
public class MOV : Asm
{
public MOV()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Set addressing mode
/// </summary>
public class LAM : Asm
{
public LAM()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[1];
}
}
#endregion
#region Numeric calculation instruction
/// <summary>
/// Add
/// </summary>
public class ADD : Asm
{
public ADD()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Minus
/// </summary>
public class SUB : Asm
{
public SUB()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Multiply
/// </summary>
public class MUL : Asm
{
public MUL()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Divide
/// </summary>
public class DIV : Asm
{
public DIV()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Mod
/// </summary>
public class MOD : Asm
{
public MOD()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
#endregion
#region Numeric comparison instruction
/// <summary>
/// Equal
/// </summary>
public class CE : Asm
{
public CE()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Less or equal
/// </summary>
public class CLE : Asm
{
public CLE()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Greater or equal
/// </summary>
public class CGE : Asm
{
public CGE()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Less
/// </summary>
public class CL : Asm
{
public CL()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Greater
/// </summary>
public class CG : Asm
{
public CG()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Not equal
/// </summary>
public class CNE : Asm
{
public CNE()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
#endregion
#region Boolean operation instruction
/// <summary>
/// And
/// </summary>
public class AND : Asm
{
public AND()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Or
/// </summary>
public class OR : Asm
{
public OR()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[2];
}
}
/// <summary>
/// Not
/// </summary>
public class NOT : Asm
{
public NOT()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[1];
}
}
#endregion
#region Instruction jump
/// <summary>
/// Jump without conditions
/// </summary>
public class JMP : Asm
{
public JMP()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[1];
}
}
/// <summary>
/// Jump if false
/// </summary>
public class JF : Asm
{
public JF()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[1];
}
}
/// <summary>
/// Jump if true
/// </summary>
public class JT : Asm
{
public JT()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[1];
}
}
#endregion
#region Other special instruction
/// <summary>
/// Halt
/// </summary>
public class HLT : Asm
{
public HLT()
{
opcode = TYPE_BYTE[this.GetType()];
}
}
/// <summary>
/// Function call
/// </summary>
public class CALL : Asm
{
public CALL()
{
opcode = TYPE_BYTE[this.GetType()];
// The first operand is the index of a function in the function table,
// and the second one is the arguments count
operand = new num[2];
}
}
/// <summary>
/// Push function argument
/// Push an argument addressing mode and data
/// </summary>
public class ARG : Asm
{
public ARG()
{
opcode = TYPE_BYTE[this.GetType()];
// The first operand is the addressing mode,
// the second one is the data
operand = new num[2];
}
}
/// <summary>
/// Heap alloc request
/// </summary>
public class HAL : Asm
{
public HAL()
{
opcode = TYPE_BYTE[this.GetType()];
operand = new num[1];
}
}
#endregion
}
}