Cosmos/source/Indy.IL2CPU.Tests/AssemblerTests/X86/TestCodeGenerator.cs

885 lines
No EOL
49 KiB
C#

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 bool CRToCR = false;
public InstructionPrefixes ValidPrefixes = InstructionPrefixes.None;
public Func<string, bool> TestIsValid;
}
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<RegistersEnum> InvalidRegisters = new RegistersEnum[0];
}
private static Dictionary<Type, ConstraintsContainer> 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<Type, ConstraintsContainer>();
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 WriteTestLine(StreamWriter aOutput, Type aType, string aFormat, params object[] aParams) {
string xLine = string.Format(aFormat, aParams);
if (opcodesException.ContainsKey(aType)) {
var xData = opcodesException[aType];
if (xData.TestIsValid != null) {
if (!xData.TestIsValid(xLine)) {
return;
}
}
}
aOutput.WriteLine(xLine);
}
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<KeyValuePair<string, string[]>> GetPrefixPossibilities(Type aType) {
if (!opcodesException.ContainsKey(aType) || opcodesException[aType].ValidPrefixes == InstructionPrefixes.None) {
yield return new KeyValuePair<string, string[]>("PrefixNone", new[] { "Prefixes = InstructionPrefixes.None" });
yield break;
}
var xResult = new List<string>();
foreach (InstructionPrefixes xValue in Enum.GetValues(typeof(InstructionPrefixes))) {
if ((opcodesException[aType].ValidPrefixes & xValue) == xValue) {
yield return new KeyValuePair<string, string[]>("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) {
WriteTestLine(aOutput, aType, "\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) {
WriteTestLine(aOutput, aType, "\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) {
WriteTestLine(aOutput, aType, "\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);
{
WriteTestLine(aOutput, aType, "\t\t\tnew global::{0}{{Size = 32}};", aType.FullName);
}
WriteTestMethodFooter("InstructionSize32", aOutput);
}
if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Word) != 0))) {
WriteTestMethodHeader("InstructionSize16", aOutput);
{
WriteTestLine(aOutput, aType, "\t\t\tnew global::{0}{{Size = 16}};", aType.FullName);
}
WriteTestMethodFooter("InstructionSize16", aOutput);
}
if (!(xInfo != null && ((xInfo.InvalidSizes & Instruction.InstructionSizes.Byte) != 0))) {
WriteTestMethodHeader("InstructionSize8", aOutput);
{
WriteTestLine(aOutput, aType, "\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) {
WriteTestLine(aOutput, aType, "\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) {
WriteTestLine(aOutput, aType, "\t\t\tnew global::{0}{{{1}, Size = {2}}};", aType.FullName, xLine, xSize);
}
}
WriteTestMethodFooter(xItem.Key + "Size" + xSize, aOutput);
}
}
}
WriteTestFixtureFooter(aType, aOutput);
}
private static IEnumerable<KeyValuePair<string, string[]>> GetDestinationPossibilities(Type aType) {
var xResult = new List<string>();
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<string, string[]>("ImmediateDestination",
xResult.ToArray());
}
if (!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo == null || opcodesException[aType].DestInfo.TestMem32) {
yield return new KeyValuePair<string, string[]>("8BitMemoryAddressDestination",
new string[] { "DestinationValue = 65, DestinationIsIndirect = true" });
yield return new KeyValuePair<string, string[]>("16BitMemoryAddressDestination",
new string[] { "DestinationValue = 650, DestinationIsIndirect = true" });
yield return new KeyValuePair<string, string[]>("32BitMemoryAddressDestination",
new string[] { "DestinationValue = 650000, DestinationIsIndirect = true" });
}
if (!opcodesException.ContainsKey(aType) || opcodesException[aType].DestInfo.TestMem32) {
var xRegistersToSkip = new List<RegistersEnum>();
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<string, string[]>("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<string>();
foreach (RegistersEnum 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<string, string[]>("RegisterDestination",
xItems.ToArray());
}
}
yield break;
}
private static IEnumerable<KeyValuePair<string, string[]>> GetSourcePossibilities(Type aType) {
if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo == null || opcodesException[aType].SourceInfo.TestImmediate32) {
yield return new KeyValuePair<string, string[]>("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<string, string[]>("8BitMemoryAddressSource",
new string[] { "SourceValue = 65, SourceIsIndirect = true" });
yield return new KeyValuePair<string, string[]>("16BitMemoryAddressSource",
new string[] { "SourceValue = 650, SourceIsIndirect = true" });
yield return new KeyValuePair<string, string[]>("32BitMemoryAddressSource",
new string[] { "SourceValue = 650000, SourceIsIndirect = true" });
}
if (!opcodesException.ContainsKey(aType) || opcodesException[aType].SourceInfo.TestMem32) {
var xRegistersToSkip = new List<RegistersEnum>();
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<string, string[]>("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<string>();
foreach (RegistersEnum 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<string, string[]>("RegisterSource",
xItems.ToArray());
}
}
yield break;
}
private static IEnumerable<KeyValuePair<string, string[]>> GetDestinationWithSizePossibilities(Type aType, byte aSize) {
var xItems = new List<string>();
{
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<string, string[]>("ImmediateDestination", xItems.ToArray());
xItems.Clear();
if (ShouldTestMemoryDestination(aType, aSize)) {
yield return new KeyValuePair<string, string[]>(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<RegistersEnum>();
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<string, string[]>("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 (RegistersEnum 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<string, string[]>("RegisterDestination", xItems.ToArray());
}
}
}
private static IEnumerable<KeyValuePair<string, string[]>> GetSourceWithSizePossibilities(Type aType, byte aSize) {
var xItems = new List<string>();
{
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<string, string[]>("ImmediateSource", xItems.ToArray());
xItems.Clear();
if (ShouldTestMemorySource(aType, aSize)) {
yield return new KeyValuePair<string, string[]>(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<RegistersEnum>();
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<string, string[]>("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 (RegistersEnum 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<string, string[]>("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;
}
}
if (!opcodesException[aType].CRToCR) {
bool xSourceContainsCR = false;
xSourceContainsCR |= xSourceItem.Key.Contains("CR0");
xSourceContainsCR |= xSourceItem.Key.Contains("CR1");
xSourceContainsCR |= xSourceItem.Key.Contains("CR2");
xSourceContainsCR |= xSourceItem.Key.Contains("CR3");
xSourceContainsCR |= xSourceItem.Key.Contains("CR4");
bool xDestContainsCR = false;
xDestContainsCR |= xDestItem.Key.Contains("CR0");
xDestContainsCR |= xDestItem.Key.Contains("CR1");
xDestContainsCR |= xDestItem.Key.Contains("CR2");
xDestContainsCR |= xDestItem.Key.Contains("CR3");
xDestContainsCR |= xDestItem.Key.Contains("CR4");
if (xSourceContainsCR && xDestContainsCR) {
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) {
WriteTestLine(aOutput, aType, "\t\t\tnew global::{0}{{{1}, {2}}};", aType.FullName, xSourceLine, xLine);
}
}
}
}
WriteTestMethodFooter(xSourceItem.Key + xDestItem.Key, aOutput);
}
}
}
WriteTestFixtureFooter(aType, aOutput);
}
private static IEnumerable<KeyValuePair<string, string[]>> GetConditionPossibilities(Type aType) {
foreach (var xValue in Enum.GetNames(typeof(ConditionalTestEnum))) {
yield return new KeyValuePair<string, string[]>("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) {
WriteTestLine(aOutput, aType, "\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) {
WriteTestLine(aOutput, aType, "\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);
}
}
}