/LSO.cs
C# | 369 lines | 354 code | 15 blank | 0 comment | 100 complexity | f9493ff4065f75b93ca54346218a450a MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Text;
-
- namespace LSO
- {
- static class LSO
- {
- public class InstructionInfo
- {
- public string Official;
- public string Mnemonic;
- public byte Opcode;
- public ArgType[] ArgTypes = new ArgType[0];
-
- public InstructionInfo(byte opcode, ArgType[] argtypes)
- {
- Opcode = opcode;
- ArgTypes = argtypes;
- }
-
- public InstructionInfo()
- {
- }
-
- public InstructionInfo(string official, string mnemonic, int opcode, ArgType[] argtypes)
- {
- Official = official;
- Mnemonic = mnemonic;
- Opcode = (byte)opcode;
- ArgTypes = argtypes;
- }
-
- public int NumberOfArgs
- {
- get
- {
- return ArgTypes.Length;
- }
- }
- }
-
- public class Instruction
- {
- public InstructionInfo Info = new InstructionInfo();
- public List<Object> Arguments = new List<Object>();
-
- public int Size
- {
- get
- {
- int size = 1;
- int argcount = Info.ArgTypes.Length;
- ArgType type = new ArgType();
- for(int i = 0; i < argcount; i++)
- {
- type = Info.ArgTypes[i];
- if (type == ArgType.CodeOffset || type == ArgType.Float
- || type == ArgType.Integer || type == ArgType.LocalFrameOffset
- || type == ArgType.StateIndex || type == ArgType.StaticFrameOffset
- || type == ArgType.UserFunctionIndex)
- {
- size += 4;
- }
- else if (type == ArgType.LibFunctionIndexTwoByte)
- size += 2;
- else if (type == ArgType.LibFunctionIndexByte || type == ArgType.RType
- || type == ArgType.Type)
- {
- size += 1;
- }
- else if (type == ArgType.String)
- {
- size += Arguments[i].ToString().Length + 1;
- }
- }
- return size;
- }
- }
-
- public void FromBytes(byte[] b, int offset)
- {
- Info = LSO.InstructionByOpcode(b[offset]);
- if (Info == null)
- throw new Exception("Invalid instruction");
- offset++;
- Arguments = new List<object>();
- int intvalue;
- float floatvalue;
- short shortvalue;
- string stringvalue;
- byte[] buffer;
- foreach (ArgType type in Info.ArgTypes)
- {
- if (type == ArgType.CodeOffset
- || type == ArgType.Integer || type == ArgType.LocalFrameOffset
- || type == ArgType.StateIndex || type == ArgType.StaticFrameOffset
- || type == ArgType.UserFunctionIndex)
- {
- buffer = new byte[4];
- Buffer.BlockCopy(b, offset, buffer, 0, 4);
- if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
- intvalue = BitConverter.ToInt32(buffer, 0);
- Arguments.Add(intvalue);
- offset += 4;
- }
- else if (type == ArgType.Float)
- {
- buffer = new byte[4];
- Buffer.BlockCopy(b, offset, buffer, 0, 4);
- if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
- floatvalue = BitConverter.ToSingle(buffer, 0);
- Arguments.Add(floatvalue);
- offset += 4;
- }
- else if (type == ArgType.LibFunctionIndexByte)
- {
- Arguments.Add(b[offset]);
- offset += 2;
- }
- else if (type == ArgType.LibFunctionIndexTwoByte)
- {
- buffer = new byte[2];
- Buffer.BlockCopy(b, offset, buffer, 0, 2);
- if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
- shortvalue = BitConverter.ToInt16(buffer, 0);
- Arguments.Add(shortvalue);
- offset += 2;
- }
- else if (type == ArgType.LType)
- {
- Arguments.Add((VariableType)((b[offset] >> 4) & 0x0F));
- }
- else if (type == ArgType.RType)
- {
- Arguments.Add((VariableType)(b[offset] & 0x0F));
- offset++;
- }
- else if (type == ArgType.Type)
- {
- Arguments.Add((VariableType)b[offset]);
- offset++;
- }
- else if (type == ArgType.String)
- {
- stringvalue = "";
- while (b[offset] != 0)
- {
- stringvalue += Encoding.ASCII.GetString(b, offset, 1);
- offset++;
- }
- offset++;
- Arguments.Add(stringvalue);
- }
- }
- }
-
- public byte[] ToBytes()
- {
- byte[] b = new byte[Size];
- b[0] = Info.Opcode;
- int offset = 1;
- int argcount = Info.NumberOfArgs;
- ArgType type = new ArgType();
- byte[] buffer;
- byte ltype = 0;
- for (int i = 0; i < argcount; i++)
- {
- type = Info.ArgTypes[i];
- if (type == ArgType.LType)
- {
- ltype = Convert.ToByte(Arguments[i]);
- ltype = (byte)(ltype << 4);
- ltype = (byte)(ltype & 0xF0);
- }
- else if (type == ArgType.RType)
- {
- b[offset] = (byte)(ltype | (Convert.ToByte(Arguments[i]) & 0x0F));
- offset++;
- }
- else if (type == ArgType.Type || type == ArgType.LibFunctionIndexByte)
- {
- b[offset] = Convert.ToByte(Arguments[i]);
- offset++;
- }
- else if (type == ArgType.LibFunctionIndexTwoByte)
- {
- buffer = BitConverter.GetBytes(Convert.ToInt16(Arguments[i]));
- if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
- Buffer.BlockCopy(buffer, 0, b, offset, buffer.Length);
- offset += buffer.Length;
- }
- else if (type == ArgType.String)
- {
- string str = Convert.ToString(Arguments[i]);
- buffer = new byte[str.Length + 1];
- Buffer.BlockCopy(Encoding.ASCII.GetBytes(str), 0, b, offset, str.Length);
- offset += buffer.Length;
- }
- else if (type == ArgType.Float)
- {
- buffer = BitConverter.GetBytes(Convert.ToSingle(Arguments[i]));
- if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
- Buffer.BlockCopy(buffer, 0, b, offset, buffer.Length);
- offset += buffer.Length;
- }
- else
- {
- buffer = BitConverter.GetBytes(Convert.ToInt32(Arguments[i]));
- if (BitConverter.IsLittleEndian) Array.Reverse(buffer);
- Buffer.BlockCopy(buffer, 0, b, offset, buffer.Length);
- offset += buffer.Length;
- }
- }
- return b;
- }
-
- public override string ToString()
- {
- string s = Info.Official;
- if (Arguments.Count > 0)
- {
- s += " ";
- int argcount = Info.ArgTypes.Length;
- ArgType type = new ArgType();
- for (int i = 0; i < argcount; i++)
- {
- if (i > 0) s += ", ";
- type = Info.ArgTypes[i];
- if (type == ArgType.String)
- {
- s += "\"" + Arguments[i] + "\"";
- }
- else
- {
- s += Arguments[i].ToString();
- }
- }
- }
- return s;
- }
- }
-
- public static List<InstructionInfo> InstructionInfos = new List<InstructionInfo>();
-
- public static InstructionInfo InstructionByName(string name)
- {
- name = name.ToUpper();
- foreach (InstructionInfo info in InstructionInfos)
- {
- if (info.Official == name)
- return info;
- }
- return null;
- }
-
- public static InstructionInfo InstructionByOpcode(byte opcode)
- {
- foreach (InstructionInfo info in InstructionInfos)
- {
- if (info.Opcode == opcode)
- return info;
- }
- return null;
- }
-
- static void AddInstruction(string official, string mnemonic, int opcode, ArgType[] argtypes)
- {
- InstructionInfo info = new InstructionInfo(official, mnemonic, opcode, argtypes);
- InstructionInfos.Add(info);
- }
-
- static LSO()
- {
- AddInstruction("NOOP", "NOP", 0x00, new ArgType[0]);
- AddInstruction("POP", "DROP_NUM", 0x01, new ArgType[0]);
- AddInstruction("POPS", "DROP_STRING", 0x02, new ArgType[0]);
- AddInstruction("POPL", "DROP_LIST", 0x03, new ArgType[0]);
- AddInstruction("POPV", "DROP_VECTOR", 0x04, new ArgType[0]);
- AddInstruction("POPQ", "DROP_ROTATION", 0x05, new ArgType[0]);
- AddInstruction("POPARG", "", 0x06, new ArgType[] { ArgType.Integer });
- AddInstruction("POPIP", "", 0x07, new ArgType[0]);
- AddInstruction("POPBP", "BUILD_CALL_FRAME", 0x08, new ArgType[0]);
- AddInstruction("POPSP", "", 0x09, new ArgType[0]);
- AddInstruction("POPSLR", "", 0x0A, new ArgType[0]);
- AddInstruction("DUP", "", 0x20, new ArgType[0]);
- AddInstruction("DUPS", "", 0x21, new ArgType[0]);
- AddInstruction("DUPL", "", 0x22, new ArgType[0]);
- AddInstruction("DUPV", "", 0x23, new ArgType[0]);
- AddInstruction("DUPQ", "", 0x24, new ArgType[0]);
- AddInstruction("STORE", "STORE_L_NUMBER", 0x30, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("STORES", "STORE_L_STRING", 0x31, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("STOREL", "STORE_L_LIST", 0x32, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("STOREV", "STORE_L_VECTOR", 0x33, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("STOREQ", "STORE_L_ROTATION", 0x34, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("STOREG", "STORE_G_NUMBER", 0x35, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("STOREGS", "STORE_G_STRING", 0x36, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("STOREGL", "STORE_G_LIST", 0x37, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("STOREGV", "STORE_G_VECTOR", 0x38, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("STOREGQ", "STORE_G_ROTATION", 0x39, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("LOADP", "POP_L_NUMBER", 0x3A, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("LOADSP", "POP_L_STRING", 0x3B, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("LOADLP", "POP_L_LIST", 0x3C, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("LOADVP", "POP_L_VECTOR", 0x3D, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("LOADQP", "POP_L_ROTATION", 0x3E, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("LOADGP", "POP_G_NUMBER", 0x3F, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("LOADGSP", "POP_G_STRING", 0x40, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("LOADGLP", "POP_G_LIST", 0x41, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("LOADGVP", "POP_G_VECTOR", 0x42, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("LOADGQP", "POP_G_ROTATION", 0x43, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("PUSH", "PUSH_L_NUMBER", 0x50, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("PUSHS", "PUSH_L_STRING", 0x51, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("PUSHL", "PUSH_L_LIST", 0x52, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("PUSHV", "PUSH_L_VECTOR", 0x53, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("PUSHQ", "PUSH_L_ROTATION", 0x54, new ArgType[] { ArgType.LocalFrameOffset });
- AddInstruction("PUSHG", "PUSH_G_NUMBER", 0x55, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("PUSHGS", "PUSH_G_STRING", 0x56, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("PUSHGL", "PUSH_G_LIST", 0x57, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("PUSHGV", "PUSH_G_VECTOR", 0x58, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("PUSHGQ", "PUSH_G_ROTATION", 0x59, new ArgType[] { ArgType.StaticFrameOffset });
- AddInstruction("PUSHIP", "", 0x5A, new ArgType[0]);
- AddInstruction("PUSHBP", "PUSH_ARGS_START", 0x5B, new ArgType[0]);
- AddInstruction("PUSHSP", "PUSH_ARGS_END", 0x5C, new ArgType[0]);
- AddInstruction("PUSHARGB", "LIST_BUILD", 0x5D, new ArgType[] { ArgType.Type });
- AddInstruction("PUSHARGI", "PUSH_INTEGER", 0x5E, new ArgType[] { ArgType.Integer });
- AddInstruction("PUSHARGF", "PUSH_FLOAT", 0x5F, new ArgType[] { ArgType.Float });
- AddInstruction("PUSHARGS", "PUSH_STRING", 0x60, new ArgType[] { ArgType.String });
- AddInstruction("PUSHARGV", "PUSH_VECTOR", 0x61, new ArgType[] { ArgType.Float, ArgType.Float, ArgType.Float });
- AddInstruction("PUSHARGQ", "PUSH_ROTATION", 0x62, new ArgType[] { ArgType.Float, ArgType.Float, ArgType.Float, ArgType.Float });
- AddInstruction("PUSHE", "PUSH_VOID4", 0x63, new ArgType[0]);
- AddInstruction("PUSHEV", "PUSH_VOID12", 0x64, new ArgType[0]);
- AddInstruction("PUSHEQ", "PUSH_VOID16", 0x65, new ArgType[0]);
- AddInstruction("PUSHARGE", "PUSH_LOCAL_ALLOC", 0x66, new ArgType[] { ArgType.Integer });
- AddInstruction("ADD", "MATH_ADD", 0x70, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("SUB", "MATH_SUBTRACT", 0x71, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("MUL", "MATH_MULTIPLY", 0x72, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("DIV", "MATH_DIVIDE", 0x73, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("MOD", "MATH_MODULO", 0x74, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("EQ", "COMPARE_EQ", 0x75, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("NEQ", "COMPARE_NE", 0x76, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("LEQ", "COMPARE_LTE", 0x77, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("GEQ", "COMPARE_GTE", 0x78, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("LESS", "COMPARE_LT", 0x79, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("GREATER", "COMPARE_GT", 0x7A, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("BITAND", "BINARY_AND", 0x7B, new ArgType[0]);
- AddInstruction("BITOR", "BINARY_OR", 0x7C, new ArgType[0]);
- AddInstruction("BITXOR", "BINARY_XOR", 0x7D, new ArgType[0]);
- AddInstruction("BOOLAND", "LOGICAL_AND", 0x7E, new ArgType[0]);
- AddInstruction("BOOLOR", "LOGICAL_OR", 0x7F, new ArgType[0]);
- AddInstruction("NEG", "MATH_NEGATIVE", 0x80, new ArgType[] { ArgType.Type });
- AddInstruction("BITNOT", "COMPLEMENT", 0x81, new ArgType[0]);
- AddInstruction("BOOLNOT", "LOGICAL_NOT", 0x82, new ArgType[0]);
- AddInstruction("JUMP", "BRANCH", 0x90, new ArgType[] { ArgType.CodeOffset });
- AddInstruction("JUMPIF", "BRANCH_TRUE", 0x91, new ArgType[] { ArgType.Type, ArgType.CodeOffset });
- AddInstruction("JUMPNIF", "BRANCH_FALSE", 0x92, new ArgType[] { ArgType.Type, ArgType.CodeOffset });
- AddInstruction("STATE", "", 0x93, new ArgType[] { ArgType.StateIndex });
- AddInstruction("CALL", "CALL_FUNCTION", 0x94, new ArgType[] { ArgType.UserFunctionIndex });
- AddInstruction("RETURN", "", 0x95, new ArgType[0]);
- AddInstruction("CAST", "CAST_TYPE", 0xA0, new ArgType[] { ArgType.LType, ArgType.RType });
- AddInstruction("STACKTOS", "", 0xB0, new ArgType[] { ArgType.Integer });
- AddInstruction("STACKTOL", "MERGE_LIST", 0xB1, new ArgType[] { ArgType.Integer });
- AddInstruction("PRINT", "", 0xC0, new ArgType[] { ArgType.Type });
- AddInstruction("CALLLIB", "", 0xD0, new ArgType[] { ArgType.LibFunctionIndexByte });
- AddInstruction("CALLLIB_TWO_BYTE", "CALL_BUILTIN", 0xD1, new ArgType[] { ArgType.LibFunctionIndexTwoByte });
- AddInstruction("SHL", "BINARY_SHL", 0xE0, new ArgType[0]);
- AddInstruction("SHR", "BINARY_SHR", 0xE1, new ArgType[0]);
- }
- }
- }