using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using Indy.IL2CPU.Assembler.X86; namespace Indy.IL2CPU.Tests.AssemblerTests.X86 { public static partial class TestCodeGenerator { private static string mOutFile; class ConstraintsContainer { public Constraints SourceInfo; public Constraints DestInfo; public Instruction.InstructionSizes InvalidSizes = Instruction.InstructionSizes.None; public bool MemToMem = false; public bool ImmediateToImmediate = false; public InstructionPrefixes ValidPrefixes = InstructionPrefixes.None; } 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 Guid[0]; } private static Dictionary opcodesException; private static void Initialize() { var xTempPath = typeof(TestCodeGenerator).Assembly.Location; xTempPath = xTempPath.Substring(0, xTempPath.LastIndexOf("source", StringComparison.InvariantCultureIgnoreCase) + "source".Length); xTempPath = Path.Combine(xTempPath, "Indy.IL2CPU.Tests"); xTempPath = Path.Combine(xTempPath, "AssemblerTests"); xTempPath = Path.Combine(xTempPath, "X86"); mOutFile = Path.Combine(xTempPath, "AutoGeneratedTests.cs"); opcodesException = new Dictionary(); AddExceptions(); } public static void Execute() { Initialize(); if ((File.GetAttributes(mOutFile) & FileAttributes.ReadOnly) != 0) { throw new Exception(String.Format("File '{0}' is readonly, please check the file out!", mOutFile)); } using (var xOutput = new StreamWriter(mOutFile, false)) { xOutput.WriteLine("using System;"); xOutput.WriteLine("using System.Collections.Generic;"); xOutput.WriteLine("using System.Linq;"); xOutput.WriteLine("using System.Text;"); xOutput.WriteLine("using Indy.IL2CPU.Assembler.X86;"); xOutput.WriteLine("using NUnit.Framework;"); xOutput.WriteLine(); xOutput.WriteLine("namespace Indy.IL2CPU.Tests.AssemblerTests.X86 {"); foreach (Type type in typeof(Instruction).Assembly.GetTypes()) { GenerateSingle(type, xOutput); } xOutput.WriteLine("}"); } } private static void GenerateSingle(Type aType, StreamWriter aOutput) { if (aType.IsAbstract) { return; } if (!aType.IsSubclassOf(typeof(Instruction))) { return; } //if (!Instruction.HasEncodingOptions(aType)) { // WriteTestFixtureHeader(aType, aOutput); // { // aOutput.WriteLine("[Test]"); // aOutput.WriteLine("[Category(\"MissingEncodingOptions\")]"); // aOutput.WriteLine("public void DoTest(){"); // aOutput.WriteLine("Assert.Fail(\"No Encoding Options specified\");"); // aOutput.WriteLine("}"); // } // WriteTestFixtureFooter(aType, aOutput); // return; //} if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestinationAndSourceAndSize))) { if (aType.GetInterfaces().Contains(typeof(IInstructionWithCondition))) { GenerateInstructionWithDestinationAndSourceAndSizeAndCondition(aType, aOutput); } else { GenerateInstructionWithDestinationAndSourceAndSize(aType, aOutput); } return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestinationAndSource))) { GenerateInstructionWithDestinationAndSource(aType, aOutput); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestinationAndSize))) { GenerateInstructionWithDestinationAndSize(aType, aOutput); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithDestination))) { GenerateInstructionWithDestination(aType, aOutput); return; } if (aType.IsSubclassOf(typeof(Assembler.X86.InstructionWithSize))) { if (aType.GetInterfaces().Contains(typeof(IInstructionWithPrefix))) { GenerateInstructionWithSizeAndPrefixes(aType, aOutput); } else { GenerateInstructionWithSize(aType, aOutput); } return; } if (aType.IsSubclassOf(typeof(Assembler.X86.Instruction))) { GenerateSimpleInstruction(aType, aOutput); return; } throw new Exception("Type not handled: " + aType.FullName); } private static void WriteTestFixtureHeader(Type aType, StreamWriter aOutput) { aOutput.WriteLine("\t[TestFixture]"); aOutput.WriteLine("\tpublic partial class {0}Tests: BaseTest {{", aType.Name); } private static void WriteTestFixtureFooter(Type aType, StreamWriter aOutput) { aOutput.WriteLine("\t}"); } private static void WriteTestMethodHeader(string aName, StreamWriter aOutput) { aOutput.WriteLine("\t\t[Test]"); aOutput.WriteLine("\t\tpublic void Test{0}() {{", aName); } private static void WriteTestMethodFooter(string aName, StreamWriter aOutput) { aOutput.WriteLine("\t\t\tVerify();"); aOutput.WriteLine("\t\t}"); } private static void GenerateSimpleInstruction(Type aType, StreamWriter aOutput) { WriteTestFixtureHeader(aType, aOutput); { WriteTestMethodHeader("Instruction", aOutput); { aOutput.WriteLine("\t\t\tnew global::{0}();", aType.FullName); } WriteTestMethodFooter("Instruction", aOutput); } WriteTestFixtureFooter(aType, aOutput); } // todo: prefixes should be combined too. private static IEnumerable> GetPrefixPossibilities(Type aType) { if (!opcodesException.ContainsKey(aType) || opcodesException[aType].ValidPrefixes == InstructionPrefixes.None) { yield return new KeyValuePair("PrefixNone", new[] { "Prefixes = InstructionPrefixes.None" }); yield break; } var xResult = new List(); foreach (InstructionPrefixes xValue in Enum.GetValues(typeof(InstructionPrefixes))) { if ((opcodesException[aType].ValidPrefixes & xValue) == xValue) { yield return new KeyValuePair("Prefix" + xValue.ToString(), new[] { "Prefixes = InstructionPrefixes." + xValue.ToString() }); } } } private static void GenerateInstructionWithSizeAndPrefixes(Type aType, StreamWriter aOutput) { ConstraintsContainer xInfo = null; if (opcodesException.ContainsKey(aType)) { xInfo = opcodesException[aType]; } WriteTestFixtureHeader(aType, aOutput); { foreach (var xPrefix in GetPrefixPossibilities(aType)) { if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.DWord) != 0))) { WriteTestMethodHeader(xPrefix.Key + "InstructionSize32", aOutput); { foreach (var xPrefixLine in xPrefix.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{Size = 32, {1}}};", aType.FullName, xPrefixLine); } } WriteTestMethodFooter(xPrefix.Key + "InstructionSize32", aOutput); } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Word) != 0))) { WriteTestMethodHeader(xPrefix.Key + "InstructionSize16", aOutput); { foreach (var xPrefixLine in xPrefix.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{Size = 16, {1}}};", aType.FullName, xPrefixLine); } } WriteTestMethodFooter(xPrefix.Key + "InstructionSize16", aOutput); } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Byte) != 0))) { WriteTestMethodHeader(xPrefix.Key + "InstructionSize8", aOutput); { foreach (var xPrefixLine in xPrefix.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{Size = 8, {1}}};", aType.FullName, xPrefixLine); } } WriteTestMethodFooter(xPrefix.Key + "InstructionSize8", aOutput); } } } WriteTestFixtureFooter(aType, aOutput); } private static void GenerateInstructionWithSize(Type aType, StreamWriter aOutput) { ConstraintsContainer xInfo = null; if (opcodesException.ContainsKey(aType)) { xInfo = opcodesException[aType]; } WriteTestFixtureHeader(aType, aOutput); { if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.DWord) != 0))) { WriteTestMethodHeader("InstructionSize32", aOutput); { aOutput.WriteLine("\t\t\tnew global::{0}{{Size = 32}};", aType.FullName); } WriteTestMethodFooter("InstructionSize32", aOutput); } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Word) != 0))) { WriteTestMethodHeader("InstructionSize16", aOutput); { aOutput.WriteLine("\t\t\tnew global::{0}{{Size = 16}};", aType.FullName); } WriteTestMethodFooter("InstructionSize16", aOutput); } if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Byte) != 0))) { WriteTestMethodHeader("InstructionSize8", aOutput); { aOutput.WriteLine("\t\t\tnew global::{0}{{Size = 8}};", aType.FullName); } WriteTestMethodFooter("InstructionSize8", aOutput); } } WriteTestFixtureFooter(aType, aOutput); } private static void GenerateInstructionWithDestination(Type aType, StreamWriter aOutput) { WriteTestFixtureHeader(aType, aOutput); { foreach (var xItem in GetDestinationPossibilities(aType)) { if (xItem.Value.Length > 0) { WriteTestMethodHeader(xItem.Key, aOutput); { foreach (var xLine in xItem.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{{1}}};", aType.FullName, xLine); } } WriteTestMethodFooter(xItem.Key, aOutput); } } } WriteTestFixtureFooter(aType, aOutput); } private static bool ShouldTestMemorySource(Type aType, byte aSize) { if (!opcodesException.ContainsKey(aType)) { return true; } if (opcodesException[aType].SourceInfo == null) { return true; } switch (aSize) { case 8: return opcodesException[aType].SourceInfo.TestMem8; case 16: return opcodesException[aType].SourceInfo.TestMem16; case 32: return opcodesException[aType].SourceInfo.TestMem32; default: throw new Exception("Wrong Size: " + aSize); } } private static bool ShouldTestImmediateSource(Type aType, byte aSize) { if (!opcodesException.ContainsKey(aType)) { return true; } if (opcodesException[aType].SourceInfo == null) { return true; } switch (aSize) { case 8: return opcodesException[aType].SourceInfo.TestImmediate8; case 16: return opcodesException[aType].SourceInfo.TestImmediate16; case 32: return opcodesException[aType].SourceInfo.TestImmediate32; default: throw new Exception("Wrong Size: " + aSize); } } private static bool ShouldTestMemoryDestination(Type aType, byte aSize) { if (!opcodesException.ContainsKey(aType)) { return true; } if (opcodesException[aType].DestInfo == null) { return true; } switch (aSize) { case 8: return opcodesException[aType].DestInfo.TestMem8; case 16: return opcodesException[aType].DestInfo.TestMem16; case 32: return opcodesException[aType].DestInfo.TestMem32; default: throw new Exception("Wrong Size: " + aSize); } } private static bool ShouldTestImmediateDestination(Type aType, byte aSize) { if (!opcodesException.ContainsKey(aType)) { return true; } if (opcodesException[aType].DestInfo == null) { return true; } switch (aSize) { case 8: return opcodesException[aType].DestInfo.TestImmediate8; case 16: return opcodesException[aType].DestInfo.TestImmediate16; case 32: return opcodesException[aType].DestInfo.TestImmediate32; default: throw new Exception("Wrong Size: " + aSize); } } private static void GenerateInstructionWithDestinationAndSize(Type aType, StreamWriter aOutput) { WriteTestFixtureHeader(aType, aOutput); { foreach (var xSize in new byte[] { 8, 16, 32 }) { foreach (var xItem in GetDestinationWithSizePossibilities(aType, xSize)) { if (xItem.Value.Length == 0) { continue; } WriteTestMethodHeader(xItem.Key + "Size" + xSize, aOutput); { foreach (var xLine in xItem.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{{1}, Size = {2}}};", aType.FullName, xLine, xSize); } } WriteTestMethodFooter(xItem.Key + "Size" + xSize, aOutput); } } } WriteTestFixtureFooter(aType, aOutput); } private static IEnumerable> GetDestinationPossibilities(Type aType) { var xResult = new List(); bool xFlag = true; if (opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo != null) { xFlag = false; } if (xFlag || opcodesException[aType].DestInfo.TestImmediate32) { xResult.Add("DestinationValue = 300000"); } if (xFlag || opcodesException[aType].DestInfo.TestImmediate16) { xResult.Add("DestinationValue=30000"); } if (xFlag || opcodesException[aType].DestInfo.TestImmediate8) { xResult.Add("DestinationValue=30"); } if (xResult.Count > 0) { yield return new KeyValuePair("ImmediateDestination", xResult.ToArray()); } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo == null || opcodesException[aType].DestInfo.TestMem32) { yield return new KeyValuePair("8BitMemoryAddressDestination", new string[] { "DestinationValue = 65, DestinationIsIndirect = true" }); yield return new KeyValuePair("16BitMemoryAddressDestination", new string[] { "DestinationValue = 650, DestinationIsIndirect = true" }); yield return new KeyValuePair("32BitMemoryAddressDestination", new string[] { "DestinationValue = 650000, DestinationIsIndirect = true" }); } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo.TestMem32) { var xRegistersToSkip = new List(); if (opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.InvalidRegisters != null) { xRegistersToSkip.AddRange(opcodesException[aType].DestInfo.InvalidRegisters); } foreach (var xReg in Registers.GetRegisters()) { if (xRegistersToSkip.Contains(xReg)) { continue; } if (!Registers.Is32Bit(xReg)) { continue; } if (Registers.IsCR(xReg)) { continue; } if (!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.TestMem32)) { yield return new KeyValuePair("MemoryAtRegister" + Registers.GetRegisterName(xReg) + "Destination", new string[] { String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect=true", Registers.GetRegisterName(xReg)), //offset 8 String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect=true, DestinationDisplacement = 203", Registers.GetRegisterName(xReg)), //offset 16 String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect=true, DestinationDisplacement = 2030", Registers.GetRegisterName(xReg)), //offset 32 String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect=true, DestinationDisplacement = 203000", Registers.GetRegisterName(xReg))}); } } } if(!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo.TestRegisters) { var xItems = new List(); foreach (Guid register in Registers.GetRegisters()) { if (!aType.Namespace.Contains("SSE") && (Registers.getXMMs().Contains(register))) continue; if (Registers.getCRs().Contains(register) && (!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && (!opcodesException[aType].DestInfo.TestCR)))) continue; if ((!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.InvalidRegisters != null && (opcodesException[aType].DestInfo.InvalidRegisters.Contains(register))))) continue; if (Registers.IsSegment(register) && !(opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.TestSegments)) { continue; } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo.InvalidRegisters.Count() == 0) { if (Registers.GetSize(register) != 32) { continue; } } xItems.Add("DestinationReg = Registers." + Registers.GetRegisterName(register)); } if (xItems.Count > 0) { yield return new KeyValuePair("RegisterDestination", xItems.ToArray()); } } yield break; } private static IEnumerable> GetSourcePossibilities(Type aType) { if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo == null || opcodesException[aType].SourceInfo.TestImmediate32) { yield return new KeyValuePair("ImmediateSource", new string[] { "SourceValue = 30", "SourceValue = 300", "SourceValue = 300000" }); } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo == null || opcodesException[aType].SourceInfo.TestMem32) { yield return new KeyValuePair("8BitMemoryAddressSource", new string[] { "SourceValue = 65, SourceIsIndirect = true" }); yield return new KeyValuePair("16BitMemoryAddressSource", new string[] { "SourceValue = 650, SourceIsIndirect = true" }); yield return new KeyValuePair("32BitMemoryAddressSource", new string[] { "SourceValue = 650000, SourceIsIndirect = true" }); } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo.TestMem32) { var xRegistersToSkip = new List(); if (opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.InvalidRegisters != null) { xRegistersToSkip.AddRange(opcodesException[aType].SourceInfo.InvalidRegisters); } foreach (var xReg in Registers.GetRegisters()) { if (xRegistersToSkip.Contains(xReg)) { continue; } if (!Registers.Is32Bit(xReg)) { continue; } if (Registers.IsCR(xReg)) { continue; } if (!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.TestMem32)) { yield return new KeyValuePair("MemoryAtRegister" + Registers.GetRegisterName(xReg) + "Source", new string[] { String.Format("SourceReg = Registers.{0}, SourceIsIndirect=true", Registers.GetRegisterName(xReg)), //offset 8 String.Format("SourceReg = Registers.{0}, SourceIsIndirect=true, SourceDisplacement = 203", Registers.GetRegisterName(xReg)), //offset 16 String.Format("SourceReg = Registers.{0}, SourceIsIndirect=true, SourceDisplacement = 2030", Registers.GetRegisterName(xReg)), //offset 32 String.Format("SourceReg = Registers.{0}, SourceIsIndirect=true, SourceDisplacement = 203000", Registers.GetRegisterName(xReg))}); } } } if(!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo.TestRegisters) { var xItems = new List(); foreach (Guid register in Registers.GetRegisters()) { if (!aType.Namespace.Contains("SSE") && (Registers.getXMMs().Contains(register))) continue; if (Registers.getCRs().Contains(register) && (!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && (!opcodesException[aType].SourceInfo.TestCR)))) continue; if ((!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.InvalidRegisters != null && (opcodesException[aType].SourceInfo.InvalidRegisters.Contains(register))))) continue; if (Registers.IsSegment(register) && !(opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.TestSegments)) { continue; } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo.InvalidRegisters.Count() == 0) { if (Registers.GetSize(register) != 32) { continue; } } xItems.Add("SourceReg = Registers." + Registers.GetRegisterName(register)); } if (xItems.Count > 0) { yield return new KeyValuePair("RegisterSource", xItems.ToArray()); } } yield break; } private static IEnumerable> GetDestinationWithSizePossibilities(Type aType, byte aSize) { var xItems = new List(); { if (aSize == 8 && ShouldTestImmediateDestination(aType, aSize)) { //Test Immediate 8 xItems.Add(String.Format("DestinationValue = 30")); } if (aSize == 16 && ShouldTestImmediateDestination(aType, aSize)) { //Test Immediate 16 xItems.Add(String.Format("DestinationValue = 300")); } if (aSize == 32 && ShouldTestImmediateDestination(aType, aSize)) { //Test Immediate 32 xItems.Add(String.Format("DestinationValue = 300000")); } } yield return new KeyValuePair("ImmediateDestination", xItems.ToArray()); xItems.Clear(); if (ShouldTestMemoryDestination(aType, aSize)) { yield return new KeyValuePair(String.Format("MemoryDestination", aSize), new string[]{ //memory 8 bits address //no offset String.Format("DestinationValue = 65, DestinationIsIndirect = true"), //memory 16 bits address //no offset String.Format("DestinationValue = 650, DestinationIsIndirect = true"), // memory 32 bits address //no offset String.Format("DestinationValue = 650000, DestinationIsIndirect = true")}); } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo.TestRegisters) { var xRegistersToSkip = new List(); if (opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.InvalidRegisters != null) { xRegistersToSkip.AddRange(opcodesException[aType].DestInfo.InvalidRegisters); } foreach (var xReg in Registers.GetRegisters()) { if (xRegistersToSkip.Contains(xReg)) { continue; } if (!Registers.Is32Bit(xReg)) { continue; } if (Registers.IsCR(xReg)) { continue; } if (ShouldTestMemoryDestination(aType, aSize)) { yield return new KeyValuePair("MemoryAtRegister" + Registers.GetRegisterName(xReg) + "Destination", new string[] { //memory //no offset String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect = true", Registers.GetRegisterName(xReg)), //offset 8 String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect = true, DestinationDisplacement = 203", Registers.GetRegisterName(xReg)), //offset 16 String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect = true, DestinationDisplacement = 2030", Registers.GetRegisterName(xReg)), //offset 32 String.Format("DestinationReg = Registers.{0}, DestinationIsIndirect = true, DestinationDisplacement = 203000", Registers.GetRegisterName(xReg)) }); } } xItems.Clear(); foreach (Guid register in Registers.GetRegisters()) { if (!aType.Namespace.Contains("SSE") && (Registers.getXMMs().Contains(register))) continue; if (Registers.getCRs().Contains(register) && (!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && (!opcodesException[aType].DestInfo.TestCR)))) continue; if ((!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.InvalidRegisters != null && (opcodesException[aType].DestInfo.InvalidRegisters.Contains(register))))) continue; if (Registers.IsSegment(register) && !(opcodesException.ContainsKey(aType) && opcodesException[aType].DestInfo.TestSegments)) { continue; } if (Registers.GetSize(register) == aSize) { xItems.Add(String.Format("DestinationReg = Registers.{0}", Registers.GetRegisterName(register))); } } if (xItems.Count > 0) { yield return new KeyValuePair("RegisterDestination", xItems.ToArray()); } } } private static IEnumerable> GetSourceWithSizePossibilities(Type aType, byte aSize) { var xItems = new List(); { if (aSize == 8 && ShouldTestImmediateSource(aType, aSize)) { //Test Immediate 8 xItems.Add(String.Format("SourceValue = 30")); } if (aSize == 16 && ShouldTestImmediateSource(aType, aSize)) { //Test Immediate 16 xItems.Add(String.Format("SourceValue = 300")); } if (aSize == 32 && ShouldTestImmediateSource(aType, aSize)) { //Test Immediate 32 xItems.Add(String.Format("SourceValue = 300000")); } } yield return new KeyValuePair("ImmediateSource", xItems.ToArray()); xItems.Clear(); if (ShouldTestMemorySource(aType, aSize)) { yield return new KeyValuePair(String.Format("MemorySource", aSize), new string[]{ //memory 8 bits address //no offset String.Format("SourceValue = 65, SourceIsIndirect = true"), //memory 16 bits address //no offset String.Format("SourceValue = 650, SourceIsIndirect = true"), // memory 32 bits address //no offset String.Format("SourceValue = 650000, SourceIsIndirect = true"), }); } if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo.TestRegisters) { var xRegistersToSkip = new List(); if (opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.InvalidRegisters != null) { xRegistersToSkip.AddRange(opcodesException[aType].SourceInfo.InvalidRegisters); } foreach (var xReg in Registers.GetRegisters()) { if (xRegistersToSkip.Contains(xReg)) { continue; } if (!Registers.Is32Bit(xReg)) { continue; } if (Registers.IsCR(xReg)) { continue; } if (ShouldTestMemorySource(aType, aSize)) { yield return new KeyValuePair("MemoryAtRegister" + Registers.GetRegisterName(xReg) + "Source", new string[] { //memory //no offset String.Format("SourceReg = Registers.{0}, SourceIsIndirect = true", Registers.GetRegisterName(xReg)), //offset 8 String.Format("SourceReg = Registers.{0}, SourceIsIndirect = true, SourceDisplacement = 203", Registers.GetRegisterName(xReg)), //offset 16 String.Format("SourceReg = Registers.{0}, SourceIsIndirect = true, SourceDisplacement = 2030", Registers.GetRegisterName(xReg)), //offset 32 String.Format("SourceReg = Registers.{0}, SourceIsIndirect = true, SourceDisplacement = 203000", Registers.GetRegisterName(xReg)) }); } } xItems.Clear(); foreach (Guid register in Registers.GetRegisters()) { if (!aType.Namespace.Contains("SSE") && (Registers.getXMMs().Contains(register))) continue; if (Registers.getCRs().Contains(register) && (!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && (!opcodesException[aType].SourceInfo.TestCR)))) continue; if ((!opcodesException.ContainsKey(aType) || (opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.InvalidRegisters != null && (opcodesException[aType].SourceInfo.InvalidRegisters.Contains(register))))) continue; if (Registers.IsSegment(register) && !(opcodesException.ContainsKey(aType) && opcodesException[aType].SourceInfo.TestSegments)) { continue; } if (Registers.GetSize(register) == aSize) { xItems.Add(String.Format("SourceReg = Registers.{0}", Registers.GetRegisterName(register))); } } if (xItems.Count > 0) { yield return new KeyValuePair("RegisterSource", xItems.ToArray()); } } } private static void GenerateInstructionWithDestinationAndSource(Type aType, StreamWriter aOutput) { WriteTestFixtureHeader(aType, aOutput); { if (aType == typeof(Out)) { System.Diagnostics.Debugger.Break(); } foreach (var xSourceItem in GetSourcePossibilities(aType)) { foreach (var xDestItem in GetDestinationPossibilities(aType)) { if (opcodesException.ContainsKey(aType)) { if (!opcodesException[aType].MemToMem) { if (xSourceItem.Key.Contains("Memory") && xDestItem.Key.Contains("Memory")) { continue; } } if (!opcodesException[aType].ImmediateToImmediate) { if (xSourceItem.Key.Contains("Value") && xDestItem.Key.Contains("Value") && !xSourceItem.Key.Contains("IsIndirect") && !xDestItem.Key.Contains("IsIndirect")) { continue; } } } else { // if no exceptions known for this opcode, we dont emit tests for Memory to Memory and Immediate to Immediate if (xSourceItem.Key.Contains("Memory") && xDestItem.Key.Contains("Memory")) { continue; } if (xSourceItem.Key.Contains("Value") && xDestItem.Key.Contains("Value") && !xSourceItem.Key.Contains("IsIndirect") && !xDestItem.Key.Contains("IsIndirect")) { continue; } } if (xSourceItem.Value.Length == 0 || xDestItem.Value.Length == 0) { continue; } WriteTestMethodHeader(xSourceItem.Key + xDestItem.Key, aOutput); { foreach (var xSourceLine in xSourceItem.Value) { { foreach (var xLine in xDestItem.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{{1}, {2}}};", aType.FullName, xSourceLine, xLine); } } } } WriteTestMethodFooter(xSourceItem.Key + xDestItem.Key, aOutput); } } } WriteTestFixtureFooter(aType, aOutput); } private static IEnumerable> GetConditionPossibilities(Type aType) { foreach (var xValue in Enum.GetNames(typeof(ConditionalTestEnum))) { yield return new KeyValuePair("Condition" + xValue, new string[] { "Condition = ConditionalTestEnum." + xValue }); } } private static void GenerateInstructionWithDestinationAndSourceAndSizeAndCondition(Type aType, StreamWriter aOutput) { WriteTestFixtureHeader(aType, aOutput); { foreach (var xSize in new byte[] { 8, 16, 32 }) { if (opcodesException.ContainsKey(aType)) { if ((opcodesException[aType].InvalidSizes & ((Instruction.InstructionSizes)xSize)) == ((Instruction.InstructionSizes)xSize)) { continue; } } foreach (var xCondition in GetConditionPossibilities(aType)) { foreach (var xSourceItem in GetSourceWithSizePossibilities(aType, xSize)) { foreach (var xDestItem in GetDestinationWithSizePossibilities(aType, xSize)) { if (opcodesException.ContainsKey(aType)) { if (!opcodesException[aType].MemToMem) { if (xSourceItem.Key.Contains("Memory") && xDestItem.Key.Contains("Memory")) { continue; } } if (!opcodesException[aType].ImmediateToImmediate) { if (xSourceItem.Key.Contains("Value") && xDestItem.Key.Contains("Value") && !xSourceItem.Key.Contains("IsIndirect") && !xDestItem.Key.Contains("IsIndirect")) { continue; } } } else { // if no exceptions known for this opcode, we dont emit tests for Memory to Memory and Immediate to Immediate if (xSourceItem.Key.Contains("Memory") && xDestItem.Key.Contains("Memory")) { continue; } if (xSourceItem.Key.Contains("Immediate") && xDestItem.Key.Contains("Immediate") && !xSourceItem.Key.Contains("IsIndirect") && !xDestItem.Key.Contains("IsIndirect")) { continue; } } if (xSourceItem.Value.Length == 0 || xDestItem.Value.Length == 0 || xCondition.Value.Length == 0) { continue; } WriteTestMethodHeader(xCondition.Key + xSourceItem.Key + xDestItem.Key + "Size" + xSize, aOutput); { foreach (var xCondLine in xCondition.Value) { foreach (var xSourceLine in xSourceItem.Value) { foreach (var xLine in xDestItem.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{{1}, {2}, Size = {3}, {4}}};", aType.FullName, xSourceLine, xLine, xSize, xCondLine); } } } } WriteTestMethodFooter(xSourceItem.Key + xDestItem.Key + "Size" + xSize, aOutput); } } } } } WriteTestFixtureFooter(aType, aOutput); } private static void GenerateInstructionWithDestinationAndSourceAndSize(Type aType, StreamWriter aOutput) { WriteTestFixtureHeader(aType, aOutput); { foreach (var xSize in new byte[] { 8, 16, 32 }) { foreach (var xSourceItem in GetSourceWithSizePossibilities(aType, xSize)) { foreach (var xDestItem in GetDestinationWithSizePossibilities(aType, xSize)) { if (opcodesException.ContainsKey(aType)) { if (!opcodesException[aType].MemToMem) { if (xSourceItem.Key.Contains("Memory") && xDestItem.Key.Contains("Memory")) { continue; } } if (!opcodesException[aType].ImmediateToImmediate) { if (xSourceItem.Key.Contains("Value") && xDestItem.Key.Contains("Value") && !xSourceItem.Key.Contains("IsIndirect") && !xDestItem.Key.Contains("IsIndirect")) { continue; } } } else { // if no exceptions known for this opcode, we dont emit tests for Memory to Memory and Immediate to Immediate if (xSourceItem.Key.Contains("Memory") && xDestItem.Key.Contains("Memory")) { continue; } if (xSourceItem.Key.Contains("Immediate") && xDestItem.Key.Contains("Immediate") && !xSourceItem.Key.Contains("IsIndirect") && !xDestItem.Key.Contains("IsIndirect")) { continue; } } if (xSourceItem.Value.Length == 0 || xDestItem.Value.Length == 0) { continue; } WriteTestMethodHeader(xSourceItem.Key + xDestItem.Key + "Size" + xSize, aOutput); { foreach (var xSourceLine in xSourceItem.Value) { foreach (var xLine in xDestItem.Value) { aOutput.WriteLine("\t\t\tnew global::{0}{{{1}, {2}, Size = {3}}};", aType.FullName, xSourceLine, xLine, xSize); } } } WriteTestMethodFooter(xSourceItem.Key + xDestItem.Key + "Size" + xSize, aOutput); } } } } WriteTestFixtureFooter(aType, aOutput); } } }