using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Reflection; namespace Indy.IL2CPU.Assembler.X86 { public abstract class Instruction : Indy.IL2CPU.Assembler.Instruction { public class InstructionData { public class InstructionEncodingOption { public byte[] OpCode; /// /// If ModR/M byte needed, set to true. If true, all other fields on /// which refer to bytes, can assume an extra ModRM byte. /// public bool NeedsModRMByte; /// /// true is large, false small. if null, this option is not specific to a given size /// public bool? OperandSize; /// /// the indx in OpCode where the OperandSize bit is encoded /// public byte OperandSizeByte; /// /// the amount of bits the operandsize bit gets shifted to left, if neccessary /// public byte OperandSizeBitShiftLeft; /// /// is this EncodingOption valid for situations where the Destination is a register? /// if so, DestinationReg == Guid.Empty. if it is specific to a given register, the 32bit id is put in DestinationReg /// public Guid? DestinationReg; /// /// the index in OpCode where the DestinationReg bit is encoded /// public byte DestinationRegByte; /// /// the amount of bits the DestinationReg bits gets shifted to left, if neccessary /// public byte DestinationRegBitShiftLeft; /// /// is this EncodingOption valid for situations where the Destination operand is memory? /// public bool DestinationMemory; /// /// is this EncodingOption valid for situations where the Destination is an immediate value /// public bool DestinationImmediate; /// /// is this EncodingOption valid for situations where the Source is a register? /// if so, SourceReg == Guid.Empty. if it is specific to a given register, the 32bit id is put in SourceReg /// public Guid? SourceReg; /// /// is this EncodingOption valid for situations where the Destination operand is memory? /// public bool SourceMemory; /// /// is this EncodingOption valid for situations where the Destination is an immediate value /// public bool SourceImmediate; } public bool HasDestinationOperand; public bool HasSourceOperand; public List EncodingOptions = new List(); } private static SortedList mInstructionDatas; private static ReaderWriterLocker mInstructionDatasLocker; static Instruction() { mInstructionDatasLocker = new ReaderWriterLocker(); using (mInstructionDatasLocker.AcquireWriterLock()) { mInstructionDatas = new SortedList(new TypeComparer()); int xInstructionsWithEncodingOptions = 0; foreach (Type xType in typeof(Instruction).Assembly.GetTypes()) { if (!xType.IsSubclassOf(typeof(Instruction))) { continue; } if (!xType.Namespace.StartsWith(typeof(Instruction).Namespace)) { continue; } if (xType.IsAbstract) { continue; } var xAttrib = xType.GetCustomAttributes(typeof(OpCodeAttribute), true).FirstOrDefault() as OpCodeAttribute; if (xAttrib == null) { continue; } var xNewInstructionData = new InstructionData(); mInstructionDatas.Add(xType, xNewInstructionData); if (xType.IsSubclassOf(typeof(InstructionWithDestination))) { xNewInstructionData.HasDestinationOperand = true; } if (xType.IsSubclassOf(typeof(InstructionWithDestinationAndSource))) { xNewInstructionData.HasDestinationOperand = true; xNewInstructionData.HasSourceOperand = true; } var xMethod = xType.GetMethod("InitializeEncodingData", new Type[] { typeof(InstructionData) }); if (xMethod != null) { xMethod.Invoke(null, new object[]{xNewInstructionData}); } if (xNewInstructionData.EncodingOptions.Count > 0) { xInstructionsWithEncodingOptions++; } } Console.WriteLine("Total Instructions = {0}, Instructions with encoding data = {1}", mInstructionDatas.Count, xInstructionsWithEncodingOptions); } } protected Instruction() { } protected static string SizeToString(byte aSize) { switch (aSize) { case 8: return "byte"; case 16: return "word"; case 32: return "dword"; case 64: return "qword"; default: throw new Exception("Invalid size: " + aSize); } } } }