diff --git a/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/CreateIDT.cs b/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/CreateIDT.cs index 73d0d333e..6fa09d010 100644 --- a/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/CreateIDT.cs +++ b/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/CreateIDT.cs @@ -74,7 +74,7 @@ namespace Cosmos.Kernel.Plugs.Assemblers { SourceValue = 0x8E, Size = 8 }; - new CPUx86.ShiftRight { DestinationReg = Registers.EAX, Count = 16 }; + new CPUx86.ShiftRight { DestinationReg = Registers.EAX, SourceValue = 16 }; new CPUx86.Move { DestinationRef = new ElementReference("_NATIVE_IDT_Contents"), DestinationIsIndirect = true, diff --git a/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/DoTest.cs b/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/DoTest.cs index 99ec14ad9..0fa52555e 100644 --- a/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/DoTest.cs +++ b/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/DoTest.cs @@ -9,7 +9,7 @@ namespace Cosmos.Kernel.Plugs.Assemblers { public override void Assemble(Indy.IL2CPU.Assembler.Assembler aAssembler) { new CPUx86.Call { DestinationLabel = "_CODE_REQUESTED_BREAK_" }; new Label("DO_THE_TEST"); - new CPUx86.Interrupt(0x35); + new CPUx86.Interrupt { DestinationValue = 0x35 }; } } } diff --git a/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/ZeroFill.cs b/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/ZeroFill.cs index 31e02dd53..6efdee7d7 100644 --- a/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/ZeroFill.cs +++ b/source/Cosmos/Cosmos.Kernel.Plugs/Assemblers/ZeroFill.cs @@ -14,15 +14,15 @@ namespace Cosmos.Kernel.Plugs.Assemblers { new CPUx86.Move { DestinationReg = Registers.EDI, SourceReg = Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0xC }; //address new CPUx86.Move { DestinationReg = Registers.ECX, SourceReg = Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0x8 }; //length new CPUx86.Move { DestinationReg = Registers.EAX, SourceValue = 0 }; - new CPUx86.ShiftRight { DestinationReg = Registers.ECX, Count = 1 }; + new CPUx86.ShiftRight { DestinationReg = Registers.ECX, SourceValue = 1 }; new CPUx86.JumpIfNotCarry { DestinationLabel = ".step2" }; new CPUx86.StoreByteInString(); new CPUAll.Label(".step2"); - new CPUx86.ShiftRight { DestinationReg = Registers.ECX, Count = 1 }; + new CPUx86.ShiftRight { DestinationReg = Registers.ECX, SourceValue= 1 }; new CPUx86.JumpIfNotCarry { DestinationLabel = ".step3" }; new CPUx86.StoreWordInString(); new CPUAll.Label(".step3"); - new CPUx86.RepeatStosd(); + new CPUx86.RepeatStos{Size=32}; } } } diff --git a/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.Exceptions.cs b/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.Exceptions.cs index 2e9408340..d15d59373 100644 --- a/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.Exceptions.cs +++ b/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.Exceptions.cs @@ -7,8 +7,33 @@ using Indy.IL2CPU.Assembler.X86; namespace Indy.IL2CPU.Tests.AssemblerTests.X86 { partial class InvalidOpcodeTester { private static void AddExceptions() { + opcodesException.Add(typeof(Dec), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false } + }); + opcodesException.Add(typeof(Divide), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false } + }); + opcodesException.Add(typeof(Inc), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false } + }); + opcodesException.Add(typeof(Neg), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false } + }); opcodesException.Add(typeof(Not), new ConstraintsContainer { - DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false } + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments=false } + }); + opcodesException.Add(typeof(Pop), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false, + InvalidRegisters=Registers.Get8BitRegisters(), TestMem8=false }, + InvalidSizes = Instruction.InstructionSizes.Byte + }); + opcodesException.Add(typeof(ShiftLeft), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false}, + SourceInfo = new Constraints{TestCR=false, TestMem16=false, TestMem32=false, TestMem8=false, InvalidRegisters= from item in Registers.GetRegisters()where item != Registers.CL select item, TestImmediate16=false, TestImmediate32=false} + }); + opcodesException.Add(typeof(ShiftRight), new ConstraintsContainer { + DestInfo = new Constraints { TestImmediate16 = false, TestImmediate32 = false, TestImmediate8 = false, TestCR = false, TestSegments = false }, + SourceInfo = new Constraints{TestCR=false, TestMem16=false, TestMem32=false, TestMem8=false, InvalidRegisters= from item in Registers.GetRegisters()where item != Registers.CL select item, TestImmediate16=false, TestImmediate32=false} }); } } diff --git a/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.cs b/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.cs index 209c16887..2e6047d53 100644 --- a/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.cs +++ b/source/Indy.IL2CPU.Tests/AssemblerTests/X86/InvalidOpcodeTester.cs @@ -7,6 +7,8 @@ using Indy.IL2CPU.Assembler.X86; using System.Reflection; using System.IO; using System.Diagnostics; +using System.Xml; +using Instruction=Indy.IL2CPU.Assembler.X86.Instruction; namespace Indy.IL2CPU.Tests.AssemblerTests.X86 { @@ -19,7 +21,7 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 class ConstraintsContainer { public Constraints SourceInfo; public Constraints DestInfo; - public int[] InvalidSizes; + public Instruction.InstructionSizes InvalidSizes = Instruction.InstructionSizes.None; } public class TestState { @@ -49,6 +51,7 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 public bool TestImmediate32=true; public bool TestRegisters = true; public bool TestCR=true; + public bool TestSegments = true; public IEnumerable InvalidRegisters; } @@ -136,6 +139,8 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 // 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(); } @@ -145,6 +150,57 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 // } + private 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("Instruction", xItem.Instruction); + xWriter.WriteAttributeString("Size", xItem.Size.ToString()); + if (xItem.HasDest) { + if (xItem.DestReg == Guid.Empty) { + xWriter.WriteAttributeString("DestinationReg", ""); + } else { + xWriter.WriteAttributeString("DestinationReg", Registers.GetRegisterName(xItem.DestReg)); + } + xWriter.WriteAttributeString("DestinationValue", xItem.DestValue.ToString()); + xWriter.WriteAttributeString("DestinationIsIndirect", xItem.DestIsIndirect.ToString()); + xWriter.WriteAttributeString("DestinationDisplacement", xItem.DestDisplacement.ToString()); + } else { + xWriter.WriteAttributeString("DestinationReg", ""); + xWriter.WriteAttributeString("DestinationValue", ""); + xWriter.WriteAttributeString("DestinationIsIndirect", ""); + xWriter.WriteAttributeString("DestinationDisplacement", ""); + } + if (xItem.HasSource) { + if (xItem.SourceReg == Guid.Empty) { + xWriter.WriteAttributeString("SourceReg", ""); + } else { + xWriter.WriteAttributeString("SourceReg", Registers.GetRegisterName(xItem.SourceReg)); + } + xWriter.WriteAttributeString("SourceValue", xItem.SourceValue.ToString()); + xWriter.WriteAttributeString("SourceIsIndirect", xItem.SourceIsIndirect.ToString()); + xWriter.WriteAttributeString("SourceDisplacement", xItem.SourceDisplacement.ToString()); + } else { + xWriter.WriteAttributeString("SourceReg", ""); + xWriter.WriteAttributeString("SourceValue", ""); + xWriter.WriteAttributeString("SourceIsIndirect", ""); + xWriter.WriteAttributeString("SourceDisplacement", ""); + } + xWriter.WriteAttributeString("Message", xItem.Message); + xWriter.WriteAttributeString("Succeeded", xItem.Success.ToString()); + } + xWriter.WriteEndElement(); + } + } + xWriter.WriteEndElement(); // + xWriter.WriteEndDocument(); + } + } + private static void GenerateHtml(string aFile) { using(var xWriter = new StreamWriter(aFile, false)) { xWriter.WriteLine(""); @@ -235,6 +291,9 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 } private static T CreateInstruction(Type t, byte aSize) { + if(t.GetConstructor(new Type[0])==null) { + throw new Exception("Type '" + t.FullName + "' doesnt have a parameterless constructor!"); + } var xResult = (T)Activator.CreateInstance(t); if(aSize!=0) { ((IInstructionWithSize)xResult).Size = aSize; @@ -537,10 +596,13 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 continue; if (Registers.getCRs().Contains(register) && (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && (!opcodesException[type].DestInfo.TestCR)))) continue; - if (Registers.GetRegisters().Contains(register) && - (!opcodesException.ContainsKey(type) || - (opcodesException.ContainsKey(type) && opcodesException[type].DestInfo.InvalidRegisters != null && (!opcodesException[type].DestInfo.InvalidRegisters.Contains(register))))) + 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); @@ -841,15 +903,21 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 private static void TestInstructionWithDestinationAndSize(Type type) { - Console.ForegroundColor=ConsoleColor.Cyan; - Console.WriteLine("-->Size 8"); - TestInstructionWithDestination(type, 8, null); - Console.ForegroundColor = ConsoleColor.Cyan; - Console.WriteLine("-->Size 16"); - TestInstructionWithDestination(type, 16, null); - Console.ForegroundColor = ConsoleColor.Cyan; - Console.WriteLine("-->Size 32"); - TestInstructionWithDestination(type, 32, null); + if (!opcodesException.ContainsKey(type) || ((opcodesException[type].InvalidSizes & Instruction.InstructionSizes.Byte) == 0)){ + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("-->Size 8"); + TestInstructionWithDestination(type, 8, null); + } + if (!opcodesException.ContainsKey(type) || ((opcodesException[type].InvalidSizes & Instruction.InstructionSizes.Word) == 0)) { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("-->Size 16"); + TestInstructionWithDestination(type, 16, null); + } + if (!opcodesException.ContainsKey(type) || ((opcodesException[type].InvalidSizes & Instruction.InstructionSizes.DWord) == 0)) { + Console.ForegroundColor = ConsoleColor.Cyan; + Console.WriteLine("-->Size 32"); + TestInstructionWithDestination(type, 32, null); + } } private static void TestInstructionWithDestinationAndSource(Type type) @@ -862,166 +930,7 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 PropertyInfo source = type.GetProperty("SourceValue"); PropertyInfo sindirect = type.GetProperty("SourceIsIndirect"); PropertyInfo sreg = type.GetProperty("SourceReg"); - /* - Console.ForegroundColor = ConsoleColor.Yellow; - //Test Immediate 8-->reg - if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].testImmediate8)) - { - var test = Activator.CreateInstance(type); - dest.SetValue(test, (UInt32)30, new object[0]); - if (size != 0) - psize.SetValue(test, size, new object[0]); - Console.Write("\t --> Immediate 8: "); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - } - - //Test Immediate 16 - Console.ForegroundColor = ConsoleColor.Yellow; - if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].testImmediate16)) - { - var test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)300, new object[0]); - Console.Write("\t --> Immediate 16: "); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - } - //Test Immediate 32 - Console.ForegroundColor = ConsoleColor.Yellow; - if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].testImmediate16)) - { - var test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)300000, new object[0]); - Console.Write("\t --> Immediate 32: "); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - } - //memory 16 bits - Console.ForegroundColor = ConsoleColor.Yellow; - if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].testMem16)) - { - //no offset - Console.WriteLine("\t --> Mem16"); - Console.Write("\t\t --> no offset: "); - var test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)65, new object[0]); - dindirect.SetValue(test, true, new object[0]); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - //offset 16 - Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write("\t\t --> 16bit offset: "); - test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)65, new object[0]); - dindirect.SetValue(test, true, new object[0]); - displacement.SetValue(test, 203, new object[0]); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - //offset 32 - Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write("\t\t --> 32bit offset"); - test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)65, new object[0]); - dindirect.SetValue(test, true, new object[0]); - displacement.SetValue(test, 70000, new object[0]); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - } - - Console.ForegroundColor = ConsoleColor.Yellow; - if (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && opcodesException[type].testMem32)) - { - //no offset - Console.WriteLine("\t --> Mem32"); - Console.Write("\t\t --> no offset: "); - var test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)70000, new object[0]); - dindirect.SetValue(test, true, new object[0]); - //if (Verify()) - // Console.Write("OK!"); - //else - // Console.Write("Wrong data emitted"); - Console.WriteLine(); - //offset 16 - Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write("\t\t --> 16bit offset: "); - test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)70000, new object[0]); - dindirect.SetValue(test, true, new object[0]); - displacement.SetValue(test, (Int16)203, new object[0]); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - //offset 32 - Console.ForegroundColor = ConsoleColor.Yellow; - Console.Write("\t\t --> 32bit offset"); - test = Activator.CreateInstance(type); - if (size != 0) - psize.SetValue(test, size, new object[0]); - dest.SetValue(test, (UInt32)70000, new object[0]); - dindirect.SetValue(test, true, new object[0]); - displacement.SetValue(test, (Int32)70000, new object[0]); - if (Verify()) - Console.Write("OK!"); - else - Console.Write("Wrong data emitted"); - Console.WriteLine(); - } - var testReg = Activator.CreateInstance(type); - Console.WriteLine("\tRegisters"); - foreach (Guid 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].testCR)))) - continue; - if (Registers.getRegisters().Contains(register) && (!opcodesException.ContainsKey(type) || (opcodesException.ContainsKey(type) && (!opcodesException[type].invalidDestRegisters.Contains(register))))) - continue; - if (size != 0) - psize.SetValue(testReg, size, new object[0]); - dreg.SetValue(testReg, register, new object[0]); - Console.Write("\t\t" + Registers.GetRegisterName(register) + ": "); - dest.SetValue(testReg, (UInt32)8, new object[0]); - if (Verify()) - Console.WriteLine("Ok!"); - else - Console.WriteLine("Wrong data emitted"); - Console.WriteLine(); - }*/ + } private static void TestInstructionWithDestinationAndSourceAndSize(Type type) @@ -1039,7 +948,7 @@ namespace Indy.IL2CPU.Tests.AssemblerTests.X86 private static void TestSimpleInstruction(Type type) { - var test = Activator.CreateInstance(type); + var test = CreateInstruction(type, 0); if (Verify()) Console.WriteLine("Ok!"); else diff --git a/source/Indy.IL2CPU/Assembler/x86/386AndUp/Popad.cs b/source/Indy.IL2CPU/Assembler/x86/386AndUp/Popad.cs index 5d8b83c11..76b679ebd 100644 --- a/source/Indy.IL2CPU/Assembler/x86/386AndUp/Popad.cs +++ b/source/Indy.IL2CPU/Assembler/x86/386AndUp/Popad.cs @@ -6,5 +6,10 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("popad")] public class Popad : X86.Instruction { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0x61 } + }); + } } } diff --git a/source/Indy.IL2CPU/Assembler/x86/386AndUp/Pushad.cs b/source/Indy.IL2CPU/Assembler/x86/386AndUp/Pushad.cs index 211a1c43e..15a62a830 100644 --- a/source/Indy.IL2CPU/Assembler/x86/386AndUp/Pushad.cs +++ b/source/Indy.IL2CPU/Assembler/x86/386AndUp/Pushad.cs @@ -6,5 +6,11 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("pushad")] public class Pushad: Instruction { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0x60 }, + DefaultSize=InstructionSize.DWord + }); + } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/386AndUp/SignExtendAX.cs b/source/Indy.IL2CPU/Assembler/x86/386AndUp/SignExtendAX.cs index 6734ed05e..980bdd721 100644 --- a/source/Indy.IL2CPU/Assembler/x86/386AndUp/SignExtendAX.cs +++ b/source/Indy.IL2CPU/Assembler/x86/386AndUp/SignExtendAX.cs @@ -6,16 +6,11 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("cdq")] - public class SignExtendAX : Instruction + public class SignExtendAX : InstructionWithSize { - private int mOldSize; - public SignExtendAX(int aOldSize) - { - mOldSize = aOldSize; - } public override string ToString() { - switch (mOldSize) + switch (Size) { case 4: return "cdq"; diff --git a/source/Indy.IL2CPU/Assembler/x86/Dec.cs b/source/Indy.IL2CPU/Assembler/x86/Dec.cs index e9962120d..feb085c46 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Dec.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Dec.cs @@ -6,5 +6,27 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("dec")] public class Dec : InstructionWithDestinationAndSize { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[]{0xFE}, + NeedsModRMByte = true, + InitialModRMByteValue=0x8, + OperandSizeByte=0, + DestinationMemory=true + }); //memory + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode=new byte[]{0x48}, + DestinationReg=Guid.Empty, + DestinationRegByte = 0, + AllowedSizes=InstructionSizes.DWord | InstructionSizes.Word + }); // reg + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xFE }, + NeedsModRMByte = true, + InitialModRMByteValue = 0xC8, + OperandSizeByte = 0, + DestinationReg = Guid.Empty + }); // reg + } } } diff --git a/source/Indy.IL2CPU/Assembler/x86/Divide.cs b/source/Indy.IL2CPU/Assembler/x86/Divide.cs index e05fac8a0..18399a6c1 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Divide.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Divide.cs @@ -9,5 +9,21 @@ namespace Indy.IL2CPU.Assembler.X86 { /// [OpCode("div")] public class Divide: InstructionWithDestinationAndSize { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xF6 }, + NeedsModRMByte=true, + InitialModRMByteValue = 0xF0, + OperandSizeByte=0, + DestinationReg=Guid.Empty + });// register + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] {0xF6}, + NeedsModRMByte=true, + InitialModRMByteValue = 0x30, + OperandSizeByte = 0, + DestinationMemory=true + }); // memory + } } } diff --git a/source/Indy.IL2CPU/Assembler/x86/Inc.cs b/source/Indy.IL2CPU/Assembler/x86/Inc.cs index 108e1ae64..933596991 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Inc.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Inc.cs @@ -6,5 +6,26 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("inc")] public class Inc : InstructionWithDestinationAndSize { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode=new byte[] {0x40}, + DestinationReg=Guid.Empty, + DestinationRegByte=0, + AllowedSizes = InstructionSizes.DWord | InstructionSizes.Word + }); // reg (alt) + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xFE }, + DestinationReg = Guid.Empty, + NeedsModRMByte=true, + InitialModRMByteValue=0xC0, + OperandSizeByte=0 + }); // reg + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xFE }, + DestinationMemory=true, + NeedsModRMByte = true, + OperandSizeByte = 0 + }); // memory + } } } diff --git a/source/Indy.IL2CPU/Assembler/x86/Interrupt.cs b/source/Indy.IL2CPU/Assembler/x86/Interrupt.cs index 4e399c6f9..b7ef5171c 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Interrupt.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Interrupt.cs @@ -5,25 +5,10 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("int")] - public class Interrupt : Instruction { - public readonly string Number; - - /// - /// Interrupt N4. Indicates integer overflow. - /// - public const int INTO = 4; - - public Interrupt(int aNumber) - : this(aNumber.ToString()) { - } - - public Interrupt(string aNumber) { - Number = aNumber; - } - + public class Interrupt : InstructionWithDestination { public override string ToString() { //if (Number == INTO) return "into"; - return "int " + Number; + return "int " + DestinationValue; } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/Multiply.cs b/source/Indy.IL2CPU/Assembler/x86/Multiply.cs index 9450fa9e8..1cf4ce3f7 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Multiply.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Multiply.cs @@ -6,12 +6,5 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("mul")] public class Multiply: InstructionWithDestinationAndSize { - public readonly string Address1; - public Multiply(string aAddress1) { - Address1 = aAddress1; - } - public override string ToString() { - return "mul " + Address1; - } } } diff --git a/source/Indy.IL2CPU/Assembler/x86/Neg.cs b/source/Indy.IL2CPU/Assembler/x86/Neg.cs index d59e689ba..e0c6f2d27 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Neg.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Neg.cs @@ -6,5 +6,21 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("neg")] public class Neg: InstructionWithDestinationAndSize { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode=new byte[] {0xF6}, + NeedsModRMByte=true, + InitialModRMByteValue = 0xD8, + DestinationReg=Guid.Empty, + OperandSizeByte=0 + }); // register + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[]{0xF6}, + NeedsModRMByte = true, + InitialModRMByteValue = 0x18, + DestinationMemory = true, + OperandSizeByte=0 + }); + } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/Not.cs b/source/Indy.IL2CPU/Assembler/x86/Not.cs index 54111ed3b..d3e94af67 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Not.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Not.cs @@ -11,13 +11,16 @@ namespace Indy.IL2CPU.Assembler.X86 { OpCode = new byte[] { 0xF6 }, DestinationMemory = true, NeedsModRMByte=true, + DefaultSize=InstructionSize.DWord, + OperandSizeByte=0, InitialModRMByteValue = 0x10 }); // memory aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { OpCode = new byte[] { 0xF6 }, - DestinationMemory = true, + DestinationReg = Guid.Empty, NeedsModRMByte = true, - InitialModRMByteValue = 0xD0 + InitialModRMByteValue = 0xD0, + OperandSizeByte=0 }); // register } diff --git a/source/Indy.IL2CPU/Assembler/x86/Out.cs b/source/Indy.IL2CPU/Assembler/x86/Out.cs index 86803f2a8..b3437ac04 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Out.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Out.cs @@ -5,26 +5,31 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("out")] - public class Out: Instruction { - public byte Size { - get; - set; - } + public class Out: InstructionWithDestinationAndSize { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xE6 }, + OperandSizeByte=0, + DestinationImmediate=true, + DestinationImmediateSize=InstructionSize.Byte - public byte? Port { - get; - set; + }); // fixed port (immediate) + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xEE }, + OperandSizeByte = 0, + DestinationReg=Registers.DX + }); // fixed port (register) } public override string ToString() { - string xData = ""; - switch(Size){ - case 8: xData = "al"; break; - case 16: xData = "ax"; break; - case 32: xData = "eax"; break; - default: throw new Exception("Size " + Size + " not supported in OUT instruction"); + string xReg = ""; + switch(Size) { + case 8: xReg = "al";break; + case 16: xReg = "ax"; break; + case 32: xReg = "eax"; break; + } - return "out " + (Port.HasValue ? Port.ToString() : "DX") + ", " + xData; + return base.ToString() + ", " + xReg; } } } diff --git a/source/Indy.IL2CPU/Assembler/x86/Pop.cs b/source/Indy.IL2CPU/Assembler/x86/Pop.cs index 6dcf6c7e2..014334593 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Pop.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Pop.cs @@ -3,27 +3,24 @@ using System.Linq; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("pop")] - public class Pop: InstructionWithDestination{ + public class Pop: InstructionWithDestinationAndSize{ public static void InitializeEncodingData(Instruction.InstructionData aData) { aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { - AllowedSizes = InstructionSizes.DWord, + AllowedSizes = InstructionSizes.DWord | InstructionSizes.Word, OpCode = new byte[] { 0x58 }, NeedsModRMByte = false, DestinationReg = Guid.Empty, + DefaultSize=InstructionSize.DWord, DestinationRegByte = 0 }); // pop to register aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { - AllowedSizes = InstructionSizes.DWord, + AllowedSizes = InstructionSizes.DWord | InstructionSizes.Word, OpCode = new byte[]{0x8F}, NeedsModRMByte=true, DestinationMemory=true, DefaultSize = InstructionSize.DWord }); // pop to memory } - public override string ToString() - { - return base.mMnemonic + " dword " + this.GetDestinationAsString(); - } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/Push.cs b/source/Indy.IL2CPU/Assembler/x86/Push.cs index d9e309717..755ce9487 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Push.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Push.cs @@ -5,27 +5,26 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("push")] - public class Push : InstructionWithDestination { + public class Push : InstructionWithDestinationAndSize { public static void InitializeEncodingData(Instruction.InstructionData aData) { aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { OpCode = new byte[] { 0x50 }, - AllowedSizes = InstructionSizes.DWord, DestinationReg = Guid.Empty, DestinationRegByte = 0, - DestinationRegBitShiftLeft = 0 + DestinationRegBitShiftLeft = 0, + DefaultSize = InstructionSize.DWord }); // register aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { - OpCode = new byte[] { 0x68 }, - AllowedSizes = InstructionSizes.DWord, - DestinationImmediate = true + OpCode = new byte[] { 0x6A }, + DestinationImmediate = true, + DefaultSize = InstructionSize.DWord }); // immediate aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { - AllowedSizes = InstructionSizes.DWord, OpCode = new byte[] { 0xFF }, NeedsModRMByte = true, DestinationMemory = true, - DefaultSize = InstructionSize.DWord, - InitialModRMByteValue = 0x30 + InitialModRMByteValue = 0x30, + DefaultSize = InstructionSize.DWord }); // pop to memory } diff --git a/source/Indy.IL2CPU/Assembler/x86/Registers.cs b/source/Indy.IL2CPU/Assembler/x86/Registers.cs index 7eb2c8fc6..ae26bafc6 100644 --- a/source/Indy.IL2CPU/Assembler/x86/Registers.cs +++ b/source/Indy.IL2CPU/Assembler/x86/Registers.cs @@ -182,6 +182,10 @@ namespace Indy.IL2CPU.Assembler.X86 { return aRegister == XMM0 || aRegister == XMM1 || aRegister == XMM2 || aRegister == XMM3 || aRegister == XMM4 || aRegister == XMM5 || aRegister == XMM6 || aRegister == XMM7; } + public static bool IsSegment(Guid aRegister) { + return aRegister == CS || aRegister == DS || aRegister == ES || aRegister == FS || aRegister == GS || aRegister == SS; + } + public static bool Is32Bit(Guid aRegister) { return aRegister == EAX || aRegister == EBX || aRegister == ECX || aRegister == EDX || aRegister == ESP || aRegister == EBP || aRegister == ESI || aRegister == EDI || aRegister == CR0 || aRegister == CR1 || aRegister == CR2 || aRegister == CR3 || aRegister == CR4; } diff --git a/source/Indy.IL2CPU/Assembler/x86/Registers_Old.cs b/source/Indy.IL2CPU/Assembler/x86/Registers_Old.cs deleted file mode 100644 index e5996dd50..000000000 --- a/source/Indy.IL2CPU/Assembler/x86/Registers_Old.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; - -namespace Indy.IL2CPU.Assembler.X86 { - public class Registers_Old { - public const string EAX = "eax"; - public const string AX = "ax"; - public const string AL = "al"; - public const string AH = "ah"; - public const string EBX = "ebx"; - public const string BX = "bx"; - public const string BL = "bl"; - public const string BH = "bh"; - public const string ECX = "ecx"; - public const string CX = "cx"; - public const string CL = "cl"; - public const string CH = "ch"; - public const string EDX = "edx"; - public const string DX = "dx"; - public const string DL = "dl"; - public const string DH = "dh"; - public const string AtEAX = "[eax]"; - public const string AtEBX = "[ebx]"; - public const string AtECX = "[ecx]"; - public const string AtEDX = "[edx]"; - public const string ESP = "esp"; - public const string AtESP = "[esp]"; - public const string EBP = "ebp"; - public const string AtEBP = "[EBP]"; - public const string EDI = "edi"; - public const string AtEDI = "[edi]"; - public const string ESI = "esi"; - public const string AtESI = "[esi]"; - public const string CR0 = "CR0"; - public const string CR1 = "CR1"; - public const string CR2 = "CR2"; - public const string CR3 = "CR3"; - public const string CR4 = "CR4"; - } -} -namespace Indy.IL2CPU.Assembler.x86 { - public class Registers_Old:X86.Registers_Old{} -} \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/RepeatStos.cs b/source/Indy.IL2CPU/Assembler/x86/RepeatStos.cs new file mode 100644 index 000000000..33abadef5 --- /dev/null +++ b/source/Indy.IL2CPU/Assembler/x86/RepeatStos.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.Assembler.X86 { + [OpCode("rep stos")] + public class RepeatStos: InstructionWithSize { + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xF3, 0xAA }, + OperandSizeByte=1, + DefaultSize=InstructionSize.Word + }); + } + + public override string ToString() { + switch(Size) { + case 32: + return "rep stosd"; + case 16: + return "rep stosw"; + case 8: + return "rep stosb"; + default:throw new Exception("Size not supported!"); + } + } + } +} diff --git a/source/Indy.IL2CPU/Assembler/x86/RepeatStosb.cs b/source/Indy.IL2CPU/Assembler/x86/RepeatStosb.cs deleted file mode 100644 index c6b46153b..000000000 --- a/source/Indy.IL2CPU/Assembler/x86/RepeatStosb.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Indy.IL2CPU.Assembler.X86 { - [OpCode("rep stosb")] - public class RepeatStosb : Instruction { - //public readonly string Destination; - public RepeatStosb() { - // Destination = aDestination; - } - //public override string ToString() { - // return "rep stos " + Destinati; - //} - } -} diff --git a/source/Indy.IL2CPU/Assembler/x86/RepeatStosd.cs b/source/Indy.IL2CPU/Assembler/x86/RepeatStosd.cs deleted file mode 100644 index ffabe0a78..000000000 --- a/source/Indy.IL2CPU/Assembler/x86/RepeatStosd.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace Indy.IL2CPU.Assembler.X86 { - [OpCode("rep stosd")] - public class RepeatStosd: Instruction { - //public readonly string Destination; - public RepeatStosd() { - // Destination = aDestination; - } - //public override string ToString() { - // return "rep stosddword "; - //} - } -} diff --git a/source/Indy.IL2CPU/Assembler/x86/ShiftLeft.cs b/source/Indy.IL2CPU/Assembler/x86/ShiftLeft.cs index 1c78701c3..c4ab36318 100644 --- a/source/Indy.IL2CPU/Assembler/x86/ShiftLeft.cs +++ b/source/Indy.IL2CPU/Assembler/x86/ShiftLeft.cs @@ -4,10 +4,41 @@ using System.Linq; using System.Text; namespace Indy.IL2CPU.Assembler.X86 { - [OpCode("shld")] + [OpCode("shl")] public class ShiftLeft: InstructionWithDestinationAndSourceAndSize { - public override string ToString() { - return base.ToString() + ", CL"; - } + public static void InitializeEncodingData(Instruction.InstructionData aData) { + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xD2}, + NeedsModRMByte=true, + InitialModRMByteValue = 0xE0, + OperandSizeByte=0, + DestinationReg=Guid.Empty, + SourceReg=Registers.CL + }); // register by CL + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xD2 }, + NeedsModRMByte = true, + InitialModRMByteValue = 0x20, + OperandSizeByte = 0, + DestinationMemory=true, + SourceReg = Registers.CL + }); // memory by CL + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xC0 }, + NeedsModRMByte = true, + InitialModRMByteValue = 0xE0, + OperandSizeByte = 0, + DestinationReg = Guid.Empty, + SourceImmediate=true + }); // register by immediate + aData.EncodingOptions.Add(new InstructionData.InstructionEncodingOption { + OpCode = new byte[] { 0xC0 }, + NeedsModRMByte = true, + InitialModRMByteValue = 0x20, + OperandSizeByte = 0, + DestinationMemory = true, + SourceImmediate = true + }); // memory by immediate + } } } \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/ShiftRight.cs b/source/Indy.IL2CPU/Assembler/x86/ShiftRight.cs index 63f201be1..a00ac56b9 100644 --- a/source/Indy.IL2CPU/Assembler/x86/ShiftRight.cs +++ b/source/Indy.IL2CPU/Assembler/x86/ShiftRight.cs @@ -5,18 +5,7 @@ using System.Text; namespace Indy.IL2CPU.Assembler.X86 { [OpCode("shr")] - public class ShiftRight: InstructionWithDestination { - public byte? Count { - get; - set; - } - - public override string ToString() { - if (Count.HasValue) { - return "shr " + this.GetDestinationAsString() + ", " + Count.Value.ToString(); - } else { - return "shr " + this.GetDestinationAsString() + ", CL"; - } - } + public class ShiftRight: InstructionWithDestinationAndSourceAndSize { + } } \ No newline at end of file diff --git a/source/Indy.IL2CPU/Assembler/x86/X/Ports.cs b/source/Indy.IL2CPU/Assembler/x86/X/Ports.cs index 3713025c6..7f49c6b53 100644 --- a/source/Indy.IL2CPU/Assembler/x86/X/Ports.cs +++ b/source/Indy.IL2CPU/Assembler/x86/X/Ports.cs @@ -10,7 +10,7 @@ namespace Indy.IL2CPU.Assembler.X86.X { return new PortNumber(aPort); } set { - new X86.Out { Port = aPort, Size = 16 }; + new X86.Out { DestinationValue = aPort, Size = 16 }; } } diff --git a/source/Indy.IL2CPU/Assembler/x86/_Infra/Instruction.cs b/source/Indy.IL2CPU/Assembler/x86/_Infra/Instruction.cs index 491daf201..7ff14cd13 100644 --- a/source/Indy.IL2CPU/Assembler/x86/_Infra/Instruction.cs +++ b/source/Indy.IL2CPU/Assembler/x86/_Infra/Instruction.cs @@ -15,6 +15,7 @@ namespace Indy.IL2CPU.Assembler.X86 { Word = 16, DWord = 32, QWord = 64, + All = Byte | Word| DWord } public enum InstructionSize { @@ -22,7 +23,7 @@ namespace Indy.IL2CPU.Assembler.X86 { Byte = 8, Word = 16, DWord = 32, - QWord = 64, + QWord = 64 } public class InstructionData { public class InstructionEncodingOption { @@ -37,7 +38,7 @@ namespace Indy.IL2CPU.Assembler.X86 { public bool NeedsModRMByte; public byte InitialModRMByteValue; - public InstructionSizes AllowedSizes; + public InstructionSizes AllowedSizes = InstructionSizes.All; public InstructionSize DefaultSize = InstructionSize.DWord; /// /// the indx in OpCode where the OperandSize bit is encoded @@ -71,6 +72,7 @@ namespace Indy.IL2CPU.Assembler.X86 { /// is this EncodingOption valid for situations where the Destination is an immediate value /// public bool DestinationImmediate; + public InstructionSize DestinationImmediateSize = InstructionSize.None; /// /// is this EncodingOption valid for situations where the Source is a register? @@ -171,8 +173,12 @@ namespace Indy.IL2CPU.Assembler.X86 { } aEncodingOption = null; for (int i = 0; i < aInstructionData.EncodingOptions.Count; i++) { - var xEncodingOption = aInstructionData.EncodingOptions[i]; + if(aInstructionWithSize!=null) { + if(((byte)xEncodingOption.AllowedSizes & aInstructionWithSize.Size) != aInstructionWithSize.Size ) { + continue; + } + } if (aInstructionWithDestination != null) { if (!(((xEncodingOption.DestinationMemory || xEncodingOption.DestinationReg.HasValue) && (aInstructionWithDestination.DestinationReg != Guid.Empty || aInstructionWithDestination.DestinationValue.HasValue)) || (!(xEncodingOption.DestinationMemory || xEncodingOption.DestinationReg.HasValue) && aInstructionWithDestination.DestinationReg == Guid.Empty && aInstructionWithDestination.DestinationValue.HasValue))) { @@ -224,6 +230,19 @@ namespace Indy.IL2CPU.Assembler.X86 { } } } + if ((aInstructionWithDestination.DestinationReg != Guid.Empty && !aInstructionWithDestination.DestinationIsIndirect) && + !xEncodingOption.DestinationReg.HasValue) { + continue; + } + //if(!((xEncodingOption.DestinationReg.HasValue && aInstructionWithDestination.DestinationReg != Guid.Empty && (aInstructionWithDestination.DestinationIsIndirect == xEncodingOption.DestinationMemory)) || + // (!(xEncodingOption.DestinationReg.HasValue && (aInstructionWithDestination.DestinationReg == Guid.Empty && (aInstructionWithDestination.DestinationIsIndirect == xEncodingOption.DestinationMemory)))))) { + // continue; + //} + // (!(xEncodingOption.DestinationReg.HasValue && (aInstructionWithDestination.DestinationReg==Guid.Empty) && aInstructionWithDestination.DestinationIsIndirect)) + // )) { + // continue; + //} + } if (aInstructionWithSource != null) { if (!(((xEncodingOption.SourceMemory || xEncodingOption.SourceReg.HasValue) && (aInstructionWithSource.SourceReg != Guid.Empty || aInstructionWithSource.SourceValue.HasValue)) || @@ -253,6 +272,11 @@ namespace Indy.IL2CPU.Assembler.X86 { } private static bool DetermineSize(Indy.IL2CPU.Assembler.Assembler aAssembler, out ulong aSize, Instruction aInstruction, IInstructionWithDestination aInstructionWithDestination, IInstructionWithSize aInstructionWithSize, IInstructionWithSource aInstructionWithSource, InstructionData aInstructionData, InstructionData.InstructionEncodingOption aEncodingOption) { + if(aInstructionWithSize!=null) { + if(aInstructionWithSize.Size == 0) { + aInstructionWithSize.Size = (byte)aEncodingOption.DefaultSize; + } + } aSize = (ulong)aEncodingOption.OpCode.Length; if (aEncodingOption.NeedsModRMByte) { aSize += 1; @@ -308,7 +332,11 @@ namespace Indy.IL2CPU.Assembler.X86 { } if (aInstructionWithDestination != null && aInstructionWithSize != null) { if (aInstructionWithDestination.DestinationValue.HasValue && !aInstructionWithDestination.DestinationIsIndirect) { - aSize += (ulong)aInstructionWithSize.Size / 8; + var xSize = aInstructionWithSize.Size; + if(aEncodingOption.DestinationImmediateSize!=InstructionSize.None) { + xSize = (byte)aEncodingOption.DestinationImmediateSize; + } + aSize += (ulong)xSize / 8; } } if (aInstructionWithDestination != null && aInstructionWithDestination.DestinationRef != null) { @@ -320,7 +348,7 @@ namespace Indy.IL2CPU.Assembler.X86 { if (aInstructionWithSource != null && aInstructionWithSource.SourceRef != null) { aSize += 4; } - if (aInstructionWithDestination != null && (aInstructionWithDestination.DestinationValue.HasValue && !(aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0))) { + if (aInstructionWithDestination != null && (aInstructionWithDestination.DestinationValue.HasValue && !(aInstructionWithDestination.DestinationIsIndirect && aInstructionWithDestination.DestinationDisplacement > 0) && aInstructionWithDestination.DestinationIsIndirect)) { aSize += (ulong)aEncodingOption.DefaultSize / 8; } if (aEncodingOption.DefaultSize == InstructionSize.DWord && aInstructionWithSize != null && aInstructionWithSize.Size == 16) { @@ -603,6 +631,9 @@ namespace Indy.IL2CPU.Assembler.X86 { // throw new NotImplementedException("size not known"); xInstrSize = (int)aEncodingOption.DefaultSize / 8; } + if(aEncodingOption.DestinationImmediateSize != InstructionSize.None) { + xInstrSize = ((byte)aEncodingOption.DestinationImmediateSize) / 8; + } Array.Copy(BitConverter.GetBytes(xValue), 0, xBuffer, xOffset, xInstrSize); } } diff --git a/source/Indy.IL2CPU/Assembler/x86/_Infra/InstructionWithSize.cs b/source/Indy.IL2CPU/Assembler/x86/_Infra/InstructionWithSize.cs new file mode 100644 index 000000000..8fc5c41b0 --- /dev/null +++ b/source/Indy.IL2CPU/Assembler/x86/_Infra/InstructionWithSize.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Indy.IL2CPU.Assembler.X86 { + public abstract class InstructionWithSize: Instruction, IInstructionWithSize { + protected InstructionWithSize() { + + } + + public byte Size { + get; + set; + } + + public abstract string ToString(); + } +} diff --git a/source/Indy.IL2CPU/IL/x86/Conv_I8.cs b/source/Indy.IL2CPU/IL/x86/Conv_I8.cs index 19a64d864..b99463db8 100644 --- a/source/Indy.IL2CPU/IL/x86/Conv_I8.cs +++ b/source/Indy.IL2CPU/IL/x86/Conv_I8.cs @@ -15,8 +15,8 @@ namespace Indy.IL2CPU.IL.X86 { case 1: case 2: case 4: - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.SignExtendAX(4); + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.SignExtendAX { Size = 32 }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; diff --git a/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I.cs b/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I.cs index 604c28eb1..8699d394f 100644 --- a/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I.cs +++ b/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I.cs @@ -26,14 +26,14 @@ namespace Indy.IL2CPU.IL.X86 { case 8: { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.SignExtendAX(4); + new CPUx86.SignExtendAX { Size = 32 }; //all bits of EDX == sign (EAX) new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBX }; //must be equal to EDX new CPUx86.Xor { DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.EDX }; new CPUx86.JumpIfZero { DestinationLabel = NextInstructionLabel }; //equals - new CPUx86.Interrupt(CPUx86.Interrupt.INTO); + new CPUx86.Interrupt{DestinationValue=4}; break; } diff --git a/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I8.cs b/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I8.cs index 424fd1895..0f429beaa 100644 --- a/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I8.cs +++ b/source/Indy.IL2CPU/IL/x86/Conv_Ovf_I8.cs @@ -17,7 +17,7 @@ namespace Indy.IL2CPU.IL.X86 { case 2: case 4: new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.SignExtendAX(4); + new CPUx86.SignExtendAX { Size = 32 }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; diff --git a/source/Indy.IL2CPU/IL/x86/CustomImplementations/System.Runtime.CompilerServices/RuntimeHelpersImpl.cs b/source/Indy.IL2CPU/IL/x86/CustomImplementations/System.Runtime.CompilerServices/RuntimeHelpersImpl.cs index edb5adf1b..63a58b03e 100644 --- a/source/Indy.IL2CPU/IL/x86/CustomImplementations/System.Runtime.CompilerServices/RuntimeHelpersImpl.cs +++ b/source/Indy.IL2CPU/IL/x86/CustomImplementations/System.Runtime.CompilerServices/RuntimeHelpersImpl.cs @@ -28,7 +28,7 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Runtime.CompilerServic new Assembler.X86.Push{DestinationReg=Assembler.X86.Registers.EDI, DestinationIsIndirect=true}; new Assembler.X86.Add { DestinationReg = Assembler.X86.Registers.EDI, SourceValue = 4 }; new Assembler.X86.Move { DestinationReg = Assembler.X86.Registers.EAX, SourceReg = Assembler.X86.Registers.EDI, SourceIsIndirect = true }; - new Assembler.X86.Multiply("dword [esp]"); + new Assembler.X86.Multiply{DestinationReg=Assembler.X86.Registers.ESP, DestinationIsIndirect=true, Size=32}; new Assembler.X86.Pop { DestinationReg = Assembler.X86.Registers.ECX }; new Assembler.X86.Move { DestinationReg = Assembler.X86.Registers.ECX, SourceReg = Assembler.X86.Registers.EAX }; new Assembler.X86.Move { DestinationReg = Assembler.X86.Registers.EAX, SourceValue = 0 }; diff --git a/source/Indy.IL2CPU/IL/x86/CustomImplementations/System/Assemblers/Array_InternalCopy.cs b/source/Indy.IL2CPU/IL/x86/CustomImplementations/System/Assemblers/Array_InternalCopy.cs index 8e2cb0757..fe648b352 100644 --- a/source/Indy.IL2CPU/IL/x86/CustomImplementations/System/Assemblers/Array_InternalCopy.cs +++ b/source/Indy.IL2CPU/IL/x86/CustomImplementations/System/Assemblers/Array_InternalCopy.cs @@ -21,7 +21,7 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Assemblers { new CPUx86.Pop { DestinationReg = Registers.EAX }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; // element size new CPUx86.Move { DestinationReg = CPUx86.Registers.EBX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0x18 }; - new CPUx86.Multiply("ebx"); + new CPUx86.Multiply { DestinationReg = Registers.EBX }; new CPUx86.Add { DestinationReg = Registers.EAX, SourceValue = 16 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.ESI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0x1C }; new CPUx86.Add { DestinationReg = Registers.ESI, SourceReg = Registers.EAX }; // source ptr @@ -30,7 +30,7 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Assemblers { new CPUx86.Pop { DestinationReg = Registers.EAX }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true }; new CPUx86.Move { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0x10 }; - new CPUx86.Multiply("ecx"); + new CPUx86.Multiply { DestinationReg = Registers.ECX }; new CPUx86.Add{DestinationReg = Registers.EAX, SourceValue=16}; new CPUx86.Move { DestinationReg = CPUx86.Registers.EDI, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0x14 }; new CPUx86.Add{DestinationReg = Registers.EDI, SourceReg=Registers.EAX}; @@ -40,7 +40,7 @@ namespace Indy.IL2CPU.IL.X86.CustomImplementations.System.Assemblers { new CPUx86.Add { DestinationReg = Registers.EAX, SourceValue = 12 }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX, SourceIsIndirect = true}; new CPUx86.Move { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0xC }; - new CPUx86.Multiply("edx"); + new CPUx86.Multiply { DestinationReg = Registers.EDX }; new CPUx86.Move { DestinationReg = CPUx86.Registers.ECX, SourceReg = CPUx86.Registers.EAX, }; new RepeatMovsb(); } diff --git a/source/Indy.IL2CPU/IL/x86/Ldelem_Ref.cs b/source/Indy.IL2CPU/IL/x86/Ldelem_Ref.cs index 7616aff4a..5b9a5d3b3 100644 --- a/source/Indy.IL2CPU/IL/x86/Ldelem_Ref.cs +++ b/source/Indy.IL2CPU/IL/x86/Ldelem_Ref.cs @@ -14,7 +14,7 @@ namespace Indy.IL2CPU.IL.X86 { public static void Assemble(CPU.Assembler aAssembler, uint aElementSize) { new CPUx86.Pop{DestinationReg=CPUx86.Registers.EAX}; new CPUx86.Move { DestinationReg = CPUx86.Registers.EDX, SourceValue = aElementSize }; - new CPUx86.Multiply(CPUx86.Registers_Old.EDX); + new CPUx86.Multiply { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = (ObjectImpl.FieldDataOffset + 4) }; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EAX }; diff --git a/source/Indy.IL2CPU/IL/x86/Ldelema.cs b/source/Indy.IL2CPU/IL/x86/Ldelema.cs index 66f1f7a06..4cbf851cc 100644 --- a/source/Indy.IL2CPU/IL/x86/Ldelema.cs +++ b/source/Indy.IL2CPU/IL/x86/Ldelema.cs @@ -22,7 +22,7 @@ namespace Indy.IL2CPU.IL.X86 { aAssembler.StackContents.Push(new StackContent(4, typeof(uint))); new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Move { DestinationReg = CPUx86.Registers.EDX, SourceValue = aElementSize }; - new CPUx86.Multiply(CPUx86.Registers_Old.EDX); + new CPUx86.Multiply{DestinationReg=CPUx86.Registers.EDX}; new CPUx86.Add { DestinationReg = CPUx86.Registers.EAX, SourceValue = (uint)(ObjectImpl.FieldDataOffset + 4) }; new CPUx86.Pop { DestinationReg = CPUx86.Registers.EDX }; new CPUx86.Add { DestinationReg = CPUx86.Registers.EDX, SourceReg = CPUx86.Registers.EAX }; diff --git a/source/Indy.IL2CPU/IL/x86/Op.cs b/source/Indy.IL2CPU/IL/x86/Op.cs index 2daef8d56..062858891 100644 --- a/source/Indy.IL2CPU/IL/x86/Op.cs +++ b/source/Indy.IL2CPU/IL/x86/Op.cs @@ -152,13 +152,13 @@ namespace Indy.IL2CPU.IL.X86 { if (xStackContent.Size > 4) { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; new CPUx86.Add { DestinationReg = Registers.ESP, SourceValue = 4 }; - new CPUx86.Multiply("dword [esp]"); + new CPUx86.Multiply { DestinationReg = Registers.ESP, DestinationIsIndirect = true, Size = 32 }; new CPUx86.Add { DestinationReg = Registers.ESP, SourceValue = 8 }; new Push{DestinationValue=0}; new Push { DestinationReg = CPUx86.Registers.EAX }; } else { new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Multiply("dword [esp]"); + new CPUx86.Multiply { DestinationReg = Registers.ESP, DestinationIsIndirect = true, Size = 32 }; new CPUx86.Add { DestinationReg = Registers.ESP, SourceValue = 4 }; new Push { DestinationReg = Registers.EAX }; } diff --git a/source/Indy.IL2CPU/Indy.IL2CPU.csproj b/source/Indy.IL2CPU/Indy.IL2CPU.csproj index b3bb43c90..b9b92e2ff 100644 --- a/source/Indy.IL2CPU/Indy.IL2CPU.csproj +++ b/source/Indy.IL2CPU/Indy.IL2CPU.csproj @@ -95,7 +95,6 @@ - @@ -106,6 +105,7 @@ + @@ -179,8 +179,7 @@ - - + diff --git a/source/Playgrounds/Matthijs/TestApp/Program.cs b/source/Playgrounds/Matthijs/TestApp/Program.cs index 912d30368..a59d70641 100644 --- a/source/Playgrounds/Matthijs/TestApp/Program.cs +++ b/source/Playgrounds/Matthijs/TestApp/Program.cs @@ -1,4 +1,4 @@ -//#define BINARY +#define BINARY using System; using System.Collections.Generic; using System.Linq; @@ -12,7 +12,7 @@ namespace TestApp { class Program { class Renderer : Y86 { public void DoRender() { - new Not { DestinationReg = Registers.CR0, DestinationIsIndirect = true, Size = 8 }; + new Push {Size=8, DestinationValue = 30 }; } } static void Main(string[] args) { @@ -34,7 +34,7 @@ namespace TestApp { "Output"), "TheOutput.bin"), FileMode.Create)) { xAsm.FlushBinary(xOutput, 0x200000); - } + } #else using (var xOutput = new StreamWriter(Path.Combine(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Output"),