using System; using System.Collections.Generic; using System.Linq; using System.Text; using Indy.IL2CPU.Assembler; using Indy.IL2CPU.Assembler.X86; using System.Reflection; using System.IO; using System.Diagnostics; using System.Xml; using Instruction=Indy.IL2CPU.Assembler.X86.Instruction; using System.Reflection.Emit; namespace Indy.IL2CPU.Tests.AssemblerTests.X86 { public partial class InvalidOpcodeTester { //PS. 16 bit registers function INCLUDES segment registers and pointers //PS2. By default, Control registers ARE NOT TESTED with the opcode. To test him, add a constraint with testCR = true on the opcode you wish to test //PS3. Do not add control register as invalid register since testCR handles this. //PS4. SSE/MMX instruction uses MM/XMM registers. You should not specify any constrains as it is automatically covered by checking the instruction namespace. class ConstraintsContainer { public Constraints SourceInfo; public Constraints DestInfo; public Instruction.InstructionSizes InvalidSizes = Instruction.InstructionSizes.None; public bool MemToMem = true; } public class TestState { public string Description; public bool Success; public string Message; } class Constraints { public bool TestMem32=true; public bool TestMem16=true; public bool TestMem8=true; public bool TestImmediate8=true; public bool TestImmediate16=true; public bool TestImmediate32=true; public bool TestRegisters = true; public bool TestCR = false; public bool TestSegments = false; public IEnumerable InvalidRegisters = new RegistersEnum[0]; } private const int VerificationLevel = 1; private static string nasmPath; private static Dictionary opcodesException; public static Indy.IL2CPU.Assembler.X86.Assembler x86Assembler { get; private set; } private static List mTestStates; private static void WriteStatusEntry(string aDescription, bool aSuccess, string aMessage) { mTestStates.Add(new TestState { Description=aDescription, Success = aSuccess, Message = aMessage }); } public static void Main() { Execute(); } public static void ExecuteSingle(Type type, int level) { if (type.IsAbstract) { return; } if (!type.IsSubclassOf(typeof(Instruction))) { return; } Console.WriteLine("Testing " + type.Name); var xDoTest = new Action>(delegate(Type aType, int aLevel, string aDescription, Action aInit) { if (aInit == null) { aInit = delegate { }; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestinationAndSourceAndSize))) { TestInstructionWithDestinationAndSourceAndSize(aType, aLevel, aDescription, aInstruction => aInit((Instruction)aInstruction)); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestinationAndSource))) { TestInstructionWithDestinationAndSource(aType, aLevel, aDescription, aInstruction => aInit((Instruction)aInstruction)); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestinationAndSize))) { TestInstructionWithDestinationAndSize(aType, aLevel, aDescription, aInstruction => aInit((Instruction)aInstruction)); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestination))) { TestInstructionWithDestination(aType, aLevel, aDescription, aInstruction => aInit((Instruction)aInstruction)); return; } if (type.IsSubclassOf(typeof(Assembler.X86.InstructionWithSize))) { TestInstructionWithSize(aType, aLevel, aDescription, aInstruction => aInit((Instruction)aInstruction)); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.Instruction))) { TestSimpleInstruction(aType, aDescription, aInit); return; } }); xDoTest(type, level, type.Name, null); Verify(type.Name); } public static void Initialize() { //Pre-initialization if (!Directory.Exists(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Output"))) { Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Output")); } nasmPath = Directory.GetCurrentDirectory().ToLowerInvariant(); int xPos = nasmPath.LastIndexOf("source"); nasmPath = nasmPath.Substring(0, xPos) + @"Build\Tools\NAsm\nasm.exe"; opcodesException = new Dictionary(); AddExceptions(); x86Assembler = new Assembler.X86.Assembler(); x86Assembler.Initialize(); x86Assembler.Instructions.Clear(); x86Assembler.DataMembers.Clear(); mTestStates = new List(); } public static void Execute() { Console.TreatControlCAsInput=true; Initialize(); //Determine opcodes Assembly xAsm = Assembly.Load("Indy.IL2CPU"); try { foreach (Type type in xAsm.GetTypes()) { ExecuteSingle(type, 0); } }catch(AbortException){ Console.WriteLine("Testing interrupted, still generating test results page."); }catch(Exception E){ throw new Exception("Error while testing", E); } finally { // output results to html var xFile = Path.Combine(Path.GetDirectoryName(typeof(InvalidOpcodeTester).Assembly.Location), "TestResults.html"); GenerateHtml(xFile); xFile = Path.Combine(Path.GetDirectoryName(typeof(InvalidOpcodeTester).Assembly.Location), "TestResults.xml"); GenerateXml(xFile); Console.WriteLine("Tests finished. Results have been written to '{0}'", xFile); Console.ReadLine(); } } private static void TestInstructionWithSize(Type type, int aTestLevel, string aDescription, Action aInitInstruction) { ConstraintsContainer xInfo=null; if (opcodesException.ContainsKey(type)) { xInfo = opcodesException[type]; } if (aInitInstruction == null) { aInitInstruction = delegate { }; } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.DWord) != 0))) { var xInstruction = CreateInstruction(type, 32); aInitInstruction(xInstruction); if (aTestLevel <= VerificationLevel) { Verify(aDescription + ", size 32"); } } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Word) != 0))) { var xInstruction = CreateInstruction(type, 16); aInitInstruction(xInstruction); if (aTestLevel <= VerificationLevel) { Verify(aDescription + ", size 32"); } } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Byte) != 0))) { var xInstruction = CreateInstruction(type, 8); aInitInstruction(xInstruction); if (aTestLevel <= VerificationLevel) { Verify(aDescription + ", size 32"); } } if (aTestLevel <= VerificationLevel) { Verify(aDescription); } } public class AbortException: Exception { // } public static void GenerateXml(string aFile) { using(var xWriter = XmlWriter.Create(aFile)) { xWriter.WriteStartDocument(); xWriter.WriteStartElement("TestResults"); { foreach (var xItem in mTestStates) { xWriter.WriteStartElement("TestCase"); { xWriter.WriteAttributeString("Description", xItem.Description); xWriter.WriteAttributeString("Message", xItem.Message); xWriter.WriteAttributeString("Succeeded", xItem.Success.ToString()); } xWriter.WriteEndElement(); } } xWriter.WriteEndElement(); // xWriter.WriteEndDocument(); } } public static void GenerateHtml(string aFile) { using(var xWriter = new StreamWriter(aFile, false)) { xWriter.WriteLine(""); xWriter.WriteLine("

Failing Tests:


"); Action> WriteList = delegate(IEnumerable aList) { foreach (var xItem in aList) { xWriter.WriteLine(""); xWriter.WriteLine("{0}", xItem.Description); xWriter.WriteLine("{0}", xItem.Success); xWriter.WriteLine("{0}", xItem.Message); xWriter.WriteLine(""); } }; xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); WriteList((from item in mTestStates where !item.Success select item)); xWriter.WriteLine("
DescriptionSuccessMessage
"); xWriter.WriteLine("

Passing tests:


"); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); xWriter.WriteLine(""); WriteList((from item in mTestStates where item.Success select item)); xWriter.WriteLine("
DescriptionSuccessMessage
"); xWriter.Flush(); } } private static void TestInstructionWithDestination(Type type, int aLevel, string aDescription, Action aInitInstruction) { TestInstructionWithDestination(type, 0, aLevel, aDescription, aInitInstruction); } private static T CreateInstruction(Type t, byte aSize) { var xResult = (T)Activator.CreateInstance(t); if(aSize!=0) { ((IInstructionWithSize)xResult).Size = aSize; } return xResult; } private static void TestInstructionWithDestination(Type type, byte size, int aLevel, string aDescription, Action aInitInstruction) { if(aInitInstruction==null) { aInitInstruction = delegate { }; } IInstructionWithDestination xInstruction=null; //Test Immediate 8 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestImmediate8)) { xInstruction = CreateInstruction(type, size); xInstruction.DestinationValue = 30; aInitInstruction(xInstruction); if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit immediate"); } } //Test Immediate 16 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestImmediate16)) { xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 300; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit immediate"); } } //Test Immediate 32 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestImmediate32)) { xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 300000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit immediate"); } } //memory 8 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestMem8)) { //no offset xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 65; xInstruction.DestinationIsIndirect = true; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory, no offset"); } //offset 8 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 65; xInstruction.DestinationIsIndirect=true; xInstruction.DestinationDisplacement = 203; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory, 8bit offset"); } //offset 16 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 65; xInstruction.DestinationIsIndirect=true; xInstruction.DestinationDisplacement = 2030; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory, 16bit offset"); } //offset 32 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 65; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement=70000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory, 32bit offset"); } } //memory 16 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestMem16)) { //no offset xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650; xInstruction.DestinationIsIndirect=true; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory, no offset"); } //offset 8 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 203; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory, 8bit offset"); } //offset 16 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650; xInstruction.DestinationIsIndirect=true; xInstruction.DestinationDisplacement = 2003; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory, 16bit offset"); } //offset 32 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650; xInstruction.DestinationIsIndirect=true; xInstruction.DestinationDisplacement = 70000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory, 32bit offset"); } } // mem32 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestMem32)) { //no offset xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650000; xInstruction.DestinationIsIndirect = true; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory, no offset"); } //offset 8 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650000; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 203; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory, 8bit offset"); } //offset 16 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650000; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 2003; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory, 16bit offset"); } //offset 32 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationValue = 650000; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 70000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory, 32bit offset"); } } if (!opcodesException.ContainsKey(type) || opcodesException[type].DestInfo.TestRegisters) { var xRegistersToSkip = new List(); if (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.InvalidRegisters != null) { xRegistersToSkip.AddRange(opcodesException[type].DestInfo.InvalidRegisters); } foreach (var xReg in Registers.GetRegisters()) { if (xRegistersToSkip.Contains(xReg)) { continue; } if (!Registers.Is32Bit(xReg)) { continue; } if (Registers.IsCR(xReg)) { continue; } //memory 8 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestMem8)) { //no offset xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory at reg, no offset"); } //offset 8 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 203; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory at reg, 8bit offset"); } //offset 16 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 2030; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory at reg, 16bit offset"); } //offset 32 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 70000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 8bit memory at reg, 32bit offset"); } } //memory 16 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestMem16)) { //no offset xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory at reg, no offset"); } //offset 8 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 203; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory at reg, 8bit offset"); } //offset 16 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 2003; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory at reg, 16bit offset"); } //offset 32 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 70000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 16bit memory at reg, 32bit offset"); } } // mem32 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestMem32)) { //no offset xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory at reg, no offset"); } //offset 8 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 203; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory at reg, 8bit offset"); } //offset 16 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 2003; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory at reg, 16bit offset"); } //offset 32 xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = xReg; xInstruction.DestinationIsIndirect = true; xInstruction.DestinationDisplacement = 70000; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination 32bit memory at reg, 32bit offset"); } } } foreach (RegistersEnum register in Registers.GetRegisters()) { if (!type.Namespace.Contains("SSE") && (Registers.getXMMs().Contains(register))) continue; if (Registers.GetCRs().Contains(register) && (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && (!opcodesException[type].DestInfo.TestCR)))) continue; if ((!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.InvalidRegisters != null && (opcodesException[type].DestInfo.InvalidRegisters.Contains(register))))) continue; if (Registers.IsSegment(register) && !(opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.TestSegments)) { continue; } if (size == 0 || Registers.GetSize(register) == size) { xInstruction = CreateInstruction(type, size); aInitInstruction(xInstruction); xInstruction.DestinationReg = register; if (aLevel <= VerificationLevel) { Verify(aDescription + ", destination reg"); } } } } } private static void TestInstructionWithSource(Type type, byte size, int aLevel, string aDescription, Action aInitInstruction) { //Test Immediate 8 if (aInitInstruction == null) { aInitInstruction = delegate { }; } if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestImmediate8)) { TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", 8-bit source value", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 30; }); } //Test Immediate 16 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestImmediate16)) { TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", 16-bit source value", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 300; }); } //Test Immediate 32 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestImmediate32)) { TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", 32-bit source value", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 300000; }); } bool xOrigMem8 = false; bool xOrigMem16 = false; bool xOrigMem32 = false; bool xNeedsReset = false; if (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo!=null) { if (!opcodesException[type].MemToMem) { xNeedsReset = true; xOrigMem8 = opcodesException[type].DestInfo.TestMem8; xOrigMem16 = opcodesException[type].DestInfo.TestMem16; xOrigMem32 = opcodesException[type].DestInfo.TestMem32; opcodesException[type].DestInfo.TestMem8 = false; opcodesException[type].DestInfo.TestMem16 = false; opcodesException[type].DestInfo.TestMem32 = false; } } try { //memory 8 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestMem8)) { //no offset TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 8-bit memory location, no offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 65; xInstruction.SourceIsIndirect = true; }); //offset 8 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 8-bit memory location, 8-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 65; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 203; }); //offset 16 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 8-bit memory location, 16-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 65; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 2030; }); //offset 32 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 8-bit memory location, 32-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 65; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 70000; }); } //memory 16 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestMem16)) { //no offset TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 16-bit memory location, no offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650; xInstruction.SourceIsIndirect = true; }); //offset 8 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 16-bit memory location, 8-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 203; }); //offset 16 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 16-bit memory location, 16-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 2003; }); //offset 32 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 16-bit memory location, 32-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 70000; }); } // mem32 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestMem32)) { //no offset TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 32-bit memory location, no offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650000; xInstruction.SourceIsIndirect = true; }); //offset 8 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 32-bit memory location, 8-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650000; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 203; }); //offset 16 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 32-bit memory location, 16-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650000; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 2003; }); //offset 32 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source 32-bit memory location, 32-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceValue = 650000; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 70000; }); } if (!opcodesException.ContainsKey(type) || opcodesException[type].SourceInfo.TestRegisters) { var xRegistersToSkip = new List(); if (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.InvalidRegisters != null) { xRegistersToSkip.AddRange(opcodesException[type].SourceInfo.InvalidRegisters); } foreach (var xReg in Registers.GetRegisters()) { if (xRegistersToSkip.Contains(xReg)) { continue; } if (!Registers.Is32Bit(xReg)) { continue; } if (Registers.IsCR(xReg)) { continue; } //memory 8 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestMem8)) { //no offset TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 8-bit, no offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; }); //offset 8 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 8-bit, 8-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 203; }); //offset 16 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 8-bit, 16-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 2030; }); //offset 32 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 8-bit, 32-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 70000; }); } //memory 16 bits if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestMem16)) { //no offset TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 16-bit, no offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; }); //offset 8 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 16-bit, 8-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 203; }); //offset 16 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 16-bit, 16-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 2003; }); //offset 32 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 16-bit, 32-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 70000; }); } // mem32 if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].SourceInfo.TestMem32)) { //no offset TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 32-bit, no offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; }); //offset 8 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 32-bit, 8-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 203; }); //offset 16 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 32-bit, 16-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 2003; }); //offset 32 TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg memory location 32-bit, 32-bit offset", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = xReg; xInstruction.SourceIsIndirect = true; xInstruction.SourceDisplacement = 70000; }); } } } } finally { if (xNeedsReset) { opcodesException[type].DestInfo.TestMem8 = xOrigMem8; opcodesException[type].DestInfo.TestMem16 = xOrigMem16; opcodesException[type].DestInfo.TestMem32 = xOrigMem32; } } foreach (RegistersEnum register in Registers.GetRegisters()) { if (!type.Namespace.Contains("SSE") && (Registers.getXMMs().Contains(register))) continue; if (Registers.GetCRs().Contains(register) && (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && (!opcodesException[type].SourceInfo.TestCR)))) continue; if (Registers.GetRegisters().Contains(register) && (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && (!(opcodesException[type].SourceInfo.InvalidRegisters != null || opcodesException[type].SourceInfo.InvalidRegisters.Contains(register)))))) continue; if (Registers.IsSegment(register) && opcodesException.ContainsKey(type) && (opcodesException[type].SourceInfo == null || !opcodesException[type].SourceInfo.TestSegments)) { continue; } if (Registers.GetSize(register) != size) { continue; } TestInstructionWithDestination(type, size, aLevel + 1, aDescription + ", source reg", delegate(IInstructionWithDestination aInstruction) { var xInstruction = (IInstructionWithSource)aInstruction; aInitInstruction(aInstruction); xInstruction.SourceReg = register; }); } if (aLevel <= VerificationLevel) { Verify(aDescription); } } private static void TestInstructionWithDestinationAndSize(Type type, int aLevel, string aDescription, Action aInitInstruction) { if (!opcodesException.ContainsKey(type) || ((opcodesException[type].InvalidSizes & Instruction.InstructionSizes.Byte) == 0)){ TestInstructionWithDestination(type, 8, aLevel + 1, aDescription + ", size 8", aInitInstruction); } if (!opcodesException.ContainsKey(type) || ((opcodesException[type].InvalidSizes & Instruction.InstructionSizes.Word) == 0)) { TestInstructionWithDestination(type, 16, aLevel + 1, aDescription + ", size 16", aInitInstruction); } if (!opcodesException.ContainsKey(type) || ((opcodesException[type].InvalidSizes & Instruction.InstructionSizes.DWord) == 0)) { TestInstructionWithDestination(type, 32, aLevel + 1, aDescription + ", size 32", aInitInstruction); } if (aLevel <= VerificationLevel) { Verify(aDescription); } } private static void TestInstructionWithDestinationAndSource(Type type, int aLevel, string aDescription, Action aInitInstruction) { TestInstructionWithSource(type, 0, aLevel+1, aDescription, aInitInstruction); if (aLevel <= VerificationLevel) { Verify(aDescription); } } private static void TestInstructionWithDestinationAndSourceAndSize(Type type, int aLevel, string aDescription, Action aInitInstruction) { TestInstructionWithSource(type, 8, aLevel + 1, aDescription + ", size 8", aInitInstruction); TestInstructionWithSource(type, 16, aLevel + 1, aDescription + ", size 16", aInitInstruction); TestInstructionWithSource(type, 32, aLevel + 1, aDescription + ", size 32", aInitInstruction); if (aLevel <= VerificationLevel) { Verify(aDescription); } } private static void TestSimpleInstruction(Type type, string aDescription, Action aInitInstruction) { var test = CreateInstruction(type, 0); aInitInstruction(test); Verify(aDescription); } private static bool Verify(string aDescription) { if (x86Assembler.Instructions.Count == 0) { return true; } String tempPath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Output"); var xNasmWriter = new StreamWriter(Path.Combine(tempPath, "TheOutput.asm"), false); FileStream xNasmReader = null; bool xResult = false; string xMessage=null; try { using (var xIndy86MS = new FileStream(Path.Combine(tempPath, "TheOutput.bin"), FileMode.Create)) { x86Assembler.FlushText(xNasmWriter); xNasmWriter.Flush(); if (xNasmWriter.BaseStream.Length == 0) { throw new Exception("No content found"); } xNasmWriter.Close(); ProcessStartInfo pinfo = new ProcessStartInfo(); pinfo.Arguments = "TheOutput.asm" + " -o " + "TheOutput"; var xErrorFile = Path.Combine(tempPath, "TheOutput.err"); pinfo.Arguments += " -E\"" + xErrorFile + "\""; if (File.Exists(xErrorFile)) { File.Delete(xErrorFile); } pinfo.WorkingDirectory = tempPath; pinfo.FileName = nasmPath; pinfo.UseShellExecute ^= true; pinfo.CreateNoWindow = true; pinfo.RedirectStandardOutput = true; pinfo.RedirectStandardError = true; Process xProc = Process.Start(pinfo); xProc.WaitForExit(); if (xProc.ExitCode != 0) { xResult = false; xMessage = "Error while invoking nasm.exe"; goto WriteResult; } else { xNasmReader = File.OpenRead(Path.Combine(tempPath, "TheOutput")); x86Assembler.FlushBinary(xIndy86MS, 0x200000); xIndy86MS.Position = 0; if (xNasmReader.Length != xIndy86MS.Length) { xNasmReader.Close(); xMessage = "Binary size mismatch"; goto WriteResult; } while (true) { var xVerData = xNasmReader.ReadByte(); var xActualData = xIndy86MS.ReadByte(); if (xVerData != xActualData) { xNasmReader.Close(); xMessage = "Binary data mismatch"; goto WriteResult; } if (xVerData == -1) { break; } } xNasmReader.Close(); xResult = true; } } WriteResult: return xResult; } catch (Exception e) { if (e.Message != "No valid EncodingOption found!") { xMessage = e.ToString(); }else{ xMessage = e.Message;} } finally { WriteStatusEntry(aDescription, xResult, xMessage); if (xNasmReader != null) xNasmReader.Close(); if (xNasmWriter != null) xNasmWriter.Close(); x86Assembler.Instructions.Clear(); x86Assembler.DataMembers.Clear(); if(Console.KeyAvailable) { Console.Read(); throw new AbortException(); } } return xResult; } private static void addSegmentRegisters(List list) { list.Add(Registers.CS); list.Add(Registers.DS); list.Add(Registers.ES); list.Add(Registers.SS); list.Add(Registers.FS); list.Add(Registers.GS); } private static void add8BitRegisters(List list) { list.Add(Registers.AL); list.Add(Registers.CL); list.Add(Registers.DL); list.Add(Registers.BL); list.Add(Registers.AH); list.Add(Registers.CH); list.Add(Registers.DH); list.Add(Registers.BH); } private static void add16BitRegisters(List list) { addSegmentRegisters(list); list.Add(Registers.AX); list.Add(Registers.BP); list.Add(Registers.BX); list.Add(Registers.CX); list.Add(Registers.DI); list.Add(Registers.DX); list.Add(Registers.SI); list.Add(Registers.SP); } private static void add32BitRegisters(List list) { list.Add(Registers.EAX); list.Add(Registers.EBP); list.Add(Registers.EBX); list.Add(Registers.ECX); list.Add(Registers.EDI); list.Add(Registers.EDX); list.Add(Registers.ESI); list.Add(Registers.ESP); } } }