From 5fb50ce0cbda7a3ef64f1a66b36e5c16b42f2977 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Sun, 3 Dec 2023 08:55:40 -0500 Subject: [PATCH 1/4] Add support for x64 and limine boot protocol --- source/Cosmos.IL2CPU/AppAssembler.cs | 3 +- source/Cosmos.IL2CPU/CompilerEngine.cs | 6 +- .../ConsoleCompilerEngineSettings.cs | 4 +- source/Cosmos.IL2CPU/CosmosAssembler.cs | 167 ++++++++++-------- .../Cosmos.IL2CPU/ICompilerEngineSettings.cs | 3 +- 5 files changed, 101 insertions(+), 82 deletions(-) diff --git a/source/Cosmos.IL2CPU/AppAssembler.cs b/source/Cosmos.IL2CPU/AppAssembler.cs index e4c69b303..24b8dfffb 100644 --- a/source/Cosmos.IL2CPU/AppAssembler.cs +++ b/source/Cosmos.IL2CPU/AppAssembler.cs @@ -49,7 +49,8 @@ internal sealed class AppAssembler : IDisposable public bool StackCorruptionDetection = false; public StackCorruptionDetectionLevel StackCorruptionDetectionLevel; public DebugMode DebugMode; - public bool IgnoreDebugStubAttribute; + public bool IgnoreDebugStubAttribute; + public string TargetArchitecture; private List mSymbols = new List(); private List mINT3Labels = new List(); private int incBinCounter = 0; diff --git a/source/Cosmos.IL2CPU/CompilerEngine.cs b/source/Cosmos.IL2CPU/CompilerEngine.cs index 95902a274..21a21c6ac 100644 --- a/source/Cosmos.IL2CPU/CompilerEngine.cs +++ b/source/Cosmos.IL2CPU/CompilerEngine.cs @@ -149,7 +149,8 @@ public bool Execute() xAsm.StackCorruptionDetectionLevel = mSettings.StackCorruptionDetectionLevel; xAsm.DebugMode = mSettings.DebugMode; xAsm.TraceAssemblies = mSettings.TraceAssemblies; - xAsm.IgnoreDebugStubAttribute = mSettings.IgnoreDebugStubAttribute; + xAsm.IgnoreDebugStubAttribute = mSettings.IgnoreDebugStubAttribute; + xAsm.TargetArchitecture = mSettings.TargetArchitecture; if (!mSettings.EnableDebug) { xAsm.ShouldOptimize = true; @@ -158,7 +159,8 @@ public bool Execute() bool VBEMultiboot = mSettings.CompileVBEMultiboot; string VBEResolution = string.IsNullOrEmpty(mSettings.VBEResolution) ? "800x600x32" : mSettings.VBEResolution; - xAsm.Assembler.RemoveBootDebugOutput = mSettings.RemoveBootDebugOutput; + xAsm.Assembler.RemoveBootDebugOutput = mSettings.RemoveBootDebugOutput; + xAsm.Assembler.TargetArchitecture = mSettings.TargetArchitecture; xAsm.Assembler.Initialize(VBEMultiboot, VBEResolution); if (mSettings.DebugMode != DebugMode.IL) diff --git a/source/Cosmos.IL2CPU/ConsoleCompilerEngineSettings.cs b/source/Cosmos.IL2CPU/ConsoleCompilerEngineSettings.cs index 2affc8974..a03684538 100644 --- a/source/Cosmos.IL2CPU/ConsoleCompilerEngineSettings.cs +++ b/source/Cosmos.IL2CPU/ConsoleCompilerEngineSettings.cs @@ -43,8 +43,8 @@ internal class ConsoleCompilerEngineSettings : ICompilerEngineSettings public bool RemoveBootDebugOutput => GetOption(nameof(RemoveBootDebugOutput)); public bool CompileVBEMultiboot => GetOption(nameof(CompileVBEMultiboot)); public string VBEResolution => GetOption(nameof(VBEResolution)); - - public bool AllowComments => GetOption(nameof(AllowComments)); + public bool AllowComments => GetOption(nameof(AllowComments)); + public string TargetArchitecture => GetOption(nameof(TargetArchitecture)); public ConsoleCompilerEngineSettings(string[] aArgs, Action aLogMessage, Action aLogError) { diff --git a/source/Cosmos.IL2CPU/CosmosAssembler.cs b/source/Cosmos.IL2CPU/CosmosAssembler.cs index 6fcab25ad..394bec59c 100644 --- a/source/Cosmos.IL2CPU/CosmosAssembler.cs +++ b/source/Cosmos.IL2CPU/CosmosAssembler.cs @@ -29,7 +29,8 @@ public CosmosAssembler(int comPort) public static bool ReadDebugStubFromDisk = true; #pragma warning restore CA2211 // Non-constant fields should not be visible - public bool RemoveBootDebugOutput = false; + public bool RemoveBootDebugOutput = false; + public string TargetArchitecture = "amd64"; public virtual void WriteDebugVideo(string aText) { @@ -232,67 +233,81 @@ public void Initialize(bool enableVBE, string VBEResolution) { uint xSig = 0xe85250d6; - //Multiboot header - DataMembers.Add(new DataMember("align", "8", true)); - DataMembers.Add(new DataMember("MultibootHeader", Array.Empty())); - DataMembers.Add(new DataMember("MultibootSignature", new uint[] { xSig })); - DataMembers.Add(new DataMember("MultibootArchitecture", 0)); - DataMembers.Add(new DataMember("MultibootLenght", "MultibootHeaderEnd - MultibootHeader", typeof(uint))); - DataMembers.Add(new DataMember("MultibootChecksum", "0x100000000 - (0xe85250d6 + 0 + (MultibootHeaderEnd - MultibootHeader))", typeof(uint))); - - if (enableVBE) - { - try - { - string[] res = VBEResolution.Split('x'); - - //Framebuffer Tag - DataMembers.Add(new DataMember("align", "8", true)); - DataMembers.Add(new DataMember("MultibootFramebufferTag", Array.Empty())); - DataMembers.Add(new DataMember("MultibootFramebufferType", (ushort)5)); - DataMembers.Add(new DataMember("MultibootFramebufferOptional", (ushort)1)); - DataMembers.Add(new DataMember("MultibootFramebufferLenght", "MultibootFramebufferTagEnd - MultibootFramebufferTag", typeof(uint))); - DataMembers.Add(new DataMember("", Int32.Parse(res[0]))); - DataMembers.Add(new DataMember("", Int32.Parse(res[1]))); - DataMembers.Add(new DataMember("", Int32.Parse(res[2]))); - - DataMembers.Add(new DataMember("MultibootFramebufferTagEnd", Array.Empty())); - } - catch - { - Console.WriteLine("VBE Resolution must be this format: 1920x1080x32"); - } - } - - // memory - DataMembers.Add(new DataMember("align", "8", true)); - DataMembers.Add(new DataMember("MultibootMemoryTag", Array.Empty())); - DataMembers.Add(new DataMember("MultibootMemoryTagType", (ushort)2)); - DataMembers.Add(new DataMember("MultibootMemoryTagOptional", (ushort)1)); - DataMembers.Add(new DataMember("MultibootMemoryTagLenght", "MultibootMemoryTagEnd - MultibootMemoryTag", typeof(uint))); - DataMembers.Add(new DataMember("MultibootHeaderAddr", ElementReference.New("MultibootSignature"))); - DataMembers.Add(new DataMember("MultibootLoadAddr", ElementReference.New("MultibootSignature"))); - DataMembers.Add(new DataMember("MultibootLoadEndAddr", ElementReference.New("_end_code"))); - DataMembers.Add(new DataMember("MultibootBSSEndAddr", ElementReference.New("_end_code"))); - DataMembers.Add(new DataMember("MultibootMemoryTagEnd", Array.Empty())); - - //Entry Address - DataMembers.Add(new DataMember("align", "8", true)); - DataMembers.Add(new DataMember("MultibootEntryTag", Array.Empty())); - DataMembers.Add(new DataMember("MultibootEntryTagType", (ushort)3)); - DataMembers.Add(new DataMember("MultibootEntryTagOptional", (ushort)1)); - DataMembers.Add(new DataMember("MultibootEntryTagLenght", "MultibootEntryTagEnd - MultibootEntryTag", typeof(uint))); - DataMembers.Add(new DataMember("MultibootEntryAddr", ElementReference.New("Kernel_Start"))); - DataMembers.Add(new DataMember("MultibootEntryTagEnd", Array.Empty())); - - //End Tag - DataMembers.Add(new DataMember("align", "8", true)); - DataMembers.Add(new DataMember("MultibootEndTag", Array.Empty())); - DataMembers.Add(new DataMember("MultibootEndTagType", (ushort)0)); - DataMembers.Add(new DataMember("MultibootEndTagOptional", (ushort)0)); - DataMembers.Add(new DataMember("MultibootEndTagEnd", Array.Empty())); - - DataMembers.Add(new DataMember("MultibootHeaderEnd", Array.Empty())); + //Multiboot header + + if (TargetArchitecture != "x86" && TargetArchitecture != "amd64") + { + throw new Exception("Unknown TargetArchitecture: " + TargetArchitecture); + } + XS.Architecture = TargetArchitecture; + + // Limine protocol does not support x86 + if (TargetArchitecture == "x86") + { + DataMembers.Add(new DataMember("align", "8", true)); + DataMembers.Add(new DataMember("MultibootHeader", Array.Empty())); + DataMembers.Add(new DataMember("MultibootSignature", new uint[] { xSig })); + DataMembers.Add(new DataMember("MultibootArchitecture", 0)); + DataMembers.Add(new DataMember("MultibootLenght", "MultibootHeaderEnd - MultibootHeader", typeof(uint))); + DataMembers.Add(new DataMember("MultibootChecksum", "0x100000000 - (0xe85250d6 + 0 + (MultibootHeaderEnd - MultibootHeader))", typeof(uint))); + + if (enableVBE) + { + try + { + string[] res = VBEResolution.Split('x'); + + //Framebuffer Tag + DataMembers.Add(new DataMember("align", "8", true)); + DataMembers.Add(new DataMember("MultibootFramebufferTag", Array.Empty())); + DataMembers.Add(new DataMember("MultibootFramebufferType", (ushort)5)); + DataMembers.Add(new DataMember("MultibootFramebufferOptional", (ushort)1)); + DataMembers.Add(new DataMember("MultibootFramebufferLenght", "MultibootFramebufferTagEnd - MultibootFramebufferTag", typeof(uint))); + DataMembers.Add(new DataMember("", Int32.Parse(res[0]))); + DataMembers.Add(new DataMember("", Int32.Parse(res[1]))); + DataMembers.Add(new DataMember("", Int32.Parse(res[2]))); + + DataMembers.Add(new DataMember("MultibootFramebufferTagEnd", Array.Empty())); + } + catch + { + Console.WriteLine("VBE Resolution must be this format: 1920x1080x32"); + } + } + + DataMembers.Add(new DataMember("align", "8", true)); + DataMembers.Add(new DataMember("MultibootMemoryTag", Array.Empty())); + DataMembers.Add(new DataMember("MultibootMemoryTagType", (ushort)2)); + DataMembers.Add(new DataMember("MultibootMemoryTagOptional", (ushort)1)); + DataMembers.Add(new DataMember("MultibootMemoryTagLenght", "MultibootMemoryTagEnd - MultibootMemoryTag", typeof(uint))); + DataMembers.Add(new DataMember("MultibootHeaderAddr", ElementReference.New("MultibootSignature"))); + DataMembers.Add(new DataMember("MultibootLoadAddr", ElementReference.New("MultibootSignature"))); + DataMembers.Add(new DataMember("MultibootLoadEndAddr", ElementReference.New("_end_code"))); + DataMembers.Add(new DataMember("MultibootBSSEndAddr", ElementReference.New("_end_code"))); + DataMembers.Add(new DataMember("MultibootMemoryTagEnd", Array.Empty())); + + //Entry Address + DataMembers.Add(new DataMember("align", "8", true)); + DataMembers.Add(new DataMember("MultibootEntryTag", Array.Empty())); + DataMembers.Add(new DataMember("MultibootEntryTagType", (ushort)3)); + DataMembers.Add(new DataMember("MultibootEntryTagOptional", (ushort)1)); + DataMembers.Add(new DataMember("MultibootEntryTagLenght", "MultibootEntryTagEnd - MultibootEntryTag", typeof(uint))); + DataMembers.Add(new DataMember("MultibootEntryAddr", ElementReference.New("Kernel_Start"))); + DataMembers.Add(new DataMember("MultibootEntryTagEnd", Array.Empty())); + + //End Tag + DataMembers.Add(new DataMember("align", "8", true)); + DataMembers.Add(new DataMember("MultibootEndTag", Array.Empty())); + DataMembers.Add(new DataMember("MultibootEndTagType", (ushort)0)); + DataMembers.Add(new DataMember("MultibootEndTagOptional", (ushort)0)); + DataMembers.Add(new DataMember("MultibootEndTagEnd", Array.Empty())); + + DataMembers.Add(new DataMember("MultibootHeaderEnd", Array.Empty())); + } + else + { + DataMembers.Add(new DataMember("limine_base_revision", new ulong[] { 0xf9562b2d5c95a6c8, 0x6a7b384944536bdc, 1 })); + } //memory DataMembers.Add(new DataMember("align", "16", true)); @@ -553,20 +568,20 @@ protected byte[] GdtDescriptor(uint aBase, uint aSize, bool aCode) xResult[4] = (byte)((aBase >> 16) & 0xFF); xResult[7] = (byte)((aBase >> 24) & 0xFF); - xResult[5] = (byte)( - // Bit 7: Present, must be 1 - 0x80 | - // Bit 6-5: Privilege, 0=kernel, 3=user - 0x00 | - // Reserved, must be 1 - 0x10 | - // Bit 3: 1=Code, 0=Data - (aCode ? 0x08 : 0x00) | - // Bit 2: Direction/Conforming - 0x00 | - // Bit 1: R/W Data (1=Writeable, 0=Read only) Code (1=Readable, 0=Not readable) - 0x02 | - // Bit 0: Accessed - Set to 0. Updated by CPU later. + xResult[5] = (byte)( + // Bit 7: Present, must be 1 + 0x80 | + // Bit 6-5: Privilege, 0=kernel, 3=user + 0x00 | + // Reserved, must be 1 + 0x10 | + // Bit 3: 1=Code, 0=Data + (aCode ? 0x08 : 0x00) | + // Bit 2: Direction/Conforming + 0x00 | + // Bit 1: R/W Data (1=Writeable, 0=Read only) Code (1=Readable, 0=Not readable) + 0x02 | + // Bit 0: Accessed - Set to 0. Updated by CPU later. 0x00 ); diff --git a/source/Cosmos.IL2CPU/ICompilerEngineSettings.cs b/source/Cosmos.IL2CPU/ICompilerEngineSettings.cs index b0e906ab2..0633f70d4 100644 --- a/source/Cosmos.IL2CPU/ICompilerEngineSettings.cs +++ b/source/Cosmos.IL2CPU/ICompilerEngineSettings.cs @@ -30,6 +30,7 @@ public interface ICompilerEngineSettings bool CompileVBEMultiboot { get; } string VBEResolution { get; } - bool AllowComments { get; } + bool AllowComments { get; } + string TargetArchitecture { get; } } } \ No newline at end of file From 7c7f154a32ae7ff2b04c35980327dcbd8ea81a93 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:09:28 -0500 Subject: [PATCH 2/4] Rename registers + fixes --- source/Cosmos.IL2CPU/AppAssembler.cs | 108 +-- source/Cosmos.IL2CPU/CosmosAssembler.cs | 40 +- source/Cosmos.IL2CPU/IL/Add.cs | 144 ++-- source/Cosmos.IL2CPU/IL/Add_Ovf.cs | 136 ++-- source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs | 134 ++-- source/Cosmos.IL2CPU/IL/And.cs | 108 +-- source/Cosmos.IL2CPU/IL/Box.cs | 90 +-- source/Cosmos.IL2CPU/IL/Branch.cs | 494 +++++++------- source/Cosmos.IL2CPU/IL/Call.cs | 318 ++++----- source/Cosmos.IL2CPU/IL/Calli.cs | 44 +- source/Cosmos.IL2CPU/IL/Callvirt.cs | 542 +++++++-------- source/Cosmos.IL2CPU/IL/Castclass.cs | 112 ++-- source/Cosmos.IL2CPU/IL/Ceq.cs | 246 +++---- source/Cosmos.IL2CPU/IL/Cgt.cs | 232 +++---- source/Cosmos.IL2CPU/IL/Cgt_Un.cs | 398 +++++------ source/Cosmos.IL2CPU/IL/Ckfinite.cs | 114 ++-- source/Cosmos.IL2CPU/IL/Clt.cs | 274 ++++---- source/Cosmos.IL2CPU/IL/Clt_Un.cs | 198 +++--- source/Cosmos.IL2CPU/IL/ConvOverflowChecks.cs | 240 +++---- source/Cosmos.IL2CPU/IL/Conv_I.cs | 74 +-- source/Cosmos.IL2CPU/IL/Conv_I1.cs | 168 ++--- source/Cosmos.IL2CPU/IL/Conv_I2.cs | 166 ++--- source/Cosmos.IL2CPU/IL/Conv_I4.cs | 150 ++--- source/Cosmos.IL2CPU/IL/Conv_I8.cs | 158 ++--- source/Cosmos.IL2CPU/IL/Conv_Ovf_I8.cs | 122 ++-- source/Cosmos.IL2CPU/IL/Conv_R4.cs | 16 +- source/Cosmos.IL2CPU/IL/Conv_R8.cs | 16 +- source/Cosmos.IL2CPU/IL/Conv_R_Un.cs | 212 +++--- source/Cosmos.IL2CPU/IL/Conv_U.cs | 76 +-- source/Cosmos.IL2CPU/IL/Conv_U1.cs | 164 ++--- source/Cosmos.IL2CPU/IL/Conv_U2.cs | 168 ++--- source/Cosmos.IL2CPU/IL/Conv_U4.cs | 150 ++--- source/Cosmos.IL2CPU/IL/Conv_U8.cs | 154 ++--- source/Cosmos.IL2CPU/IL/Cpblk.cs | 52 +- source/Cosmos.IL2CPU/IL/Div.cs | 394 +++++------ source/Cosmos.IL2CPU/IL/Div_Un.cs | 282 ++++---- source/Cosmos.IL2CPU/IL/Dup.cs | 58 +- source/Cosmos.IL2CPU/IL/Endfinally.cs | 48 +- source/Cosmos.IL2CPU/IL/Initblk.cs | 88 +-- source/Cosmos.IL2CPU/IL/Initobj.cs | 118 ++-- source/Cosmos.IL2CPU/IL/Isinst.cs | 114 ++-- source/Cosmos.IL2CPU/IL/Ldarg.cs | 394 +++++------ source/Cosmos.IL2CPU/IL/Ldarga.cs | 134 ++-- source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs | 234 +++---- source/Cosmos.IL2CPU/IL/Ldelema.cs | 142 ++-- source/Cosmos.IL2CPU/IL/Ldfld.cs | 406 ++++++------ source/Cosmos.IL2CPU/IL/Ldflda.cs | 140 ++-- source/Cosmos.IL2CPU/IL/Ldind.cs | 128 ++-- source/Cosmos.IL2CPU/IL/Ldlen.cs | 68 +- source/Cosmos.IL2CPU/IL/Ldloc.cs | 132 ++-- source/Cosmos.IL2CPU/IL/Ldloca.cs | 66 +- source/Cosmos.IL2CPU/IL/Ldobj.cs | 180 ++--- source/Cosmos.IL2CPU/IL/Ldsfld.cs | 244 +++---- source/Cosmos.IL2CPU/IL/Leave.cs | 71 +- source/Cosmos.IL2CPU/IL/Mul.cs | 250 +++---- source/Cosmos.IL2CPU/IL/Mul_Ovf.cs | 210 +++--- source/Cosmos.IL2CPU/IL/Mul_Ovf_Un.cs | 208 +++--- source/Cosmos.IL2CPU/IL/Neg.cs | 118 ++-- source/Cosmos.IL2CPU/IL/Newarr.cs | 116 ++-- source/Cosmos.IL2CPU/IL/Newobj.cs | 616 +++++++++--------- source/Cosmos.IL2CPU/IL/Not.cs | 72 +- source/Cosmos.IL2CPU/IL/Or.cs | 108 +-- source/Cosmos.IL2CPU/IL/Pop.cs | 44 +- source/Cosmos.IL2CPU/IL/Refanytype.cs | 54 +- source/Cosmos.IL2CPU/IL/Rem.cs | 416 ++++++------ source/Cosmos.IL2CPU/IL/Rem_Un.cs | 314 ++++----- source/Cosmos.IL2CPU/IL/Rethrow.cs | 38 +- source/Cosmos.IL2CPU/IL/Shl.cs | 146 ++--- source/Cosmos.IL2CPU/IL/Shr.cs | 198 +++--- source/Cosmos.IL2CPU/IL/Shr_Un.cs | 334 +++++----- source/Cosmos.IL2CPU/IL/Starg.cs | 118 ++-- source/Cosmos.IL2CPU/IL/Stelem_Ref.cs | 216 +++--- source/Cosmos.IL2CPU/IL/Stfld.cs | 234 +++---- source/Cosmos.IL2CPU/IL/Stind.cs | 28 +- source/Cosmos.IL2CPU/IL/Stloc.cs | 78 +-- source/Cosmos.IL2CPU/IL/Stobj.cs | 112 ++-- source/Cosmos.IL2CPU/IL/Stsfld.cs | 258 ++++---- source/Cosmos.IL2CPU/IL/Sub.cs | 32 +- source/Cosmos.IL2CPU/IL/Sub_Ovf.cs | 132 ++-- source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs | 128 ++-- source/Cosmos.IL2CPU/IL/Switch.cs | 56 +- source/Cosmos.IL2CPU/IL/Throw.cs | 74 +-- source/Cosmos.IL2CPU/IL/Unbox.cs | 14 +- source/Cosmos.IL2CPU/IL/Xor.cs | 78 +-- source/Cosmos.IL2CPU/ILOp.cs | 16 +- source/Cosmos.IL2CPU/Program.cs | 2 +- 86 files changed, 7041 insertions(+), 7036 deletions(-) diff --git a/source/Cosmos.IL2CPU/AppAssembler.cs b/source/Cosmos.IL2CPU/AppAssembler.cs index 24b8dfffb..b18e11fd2 100644 --- a/source/Cosmos.IL2CPU/AppAssembler.cs +++ b/source/Cosmos.IL2CPU/AppAssembler.cs @@ -142,16 +142,16 @@ private void MethodBegin(Il2cpuMethodInfo aMethod) if (DebugEnabled && StackCorruptionDetection) { // if StackCorruption detection is active, we're also going to emit a stack overflow detection - XS.Set(EAX, "Before_Kernel_Stack"); - XS.Compare(EAX, ESP); + XS.Set(RAX, "Before_Kernel_Stack"); + XS.Compare(RAX, RSP); XS.Jump(ConditionalTestEnum.LessThan, ".StackOverflowCheck_End"); XS.ClearInterruptFlag(); // don't remove the call. It seems pointless, but we need it to retrieve the EIP value XS.Call(".StackOverflowCheck_GetAddress"); XS.Label(".StackOverflowCheck_GetAddress"); XS.Exchange(BX, BX); - XS.Pop(EAX); - XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], EAX, destinationIsIndirect: true); + XS.Pop(RAX); + XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], RAX, destinationIsIndirect: true); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendStackOverflowEvent]); XS.Halt(); XS.Label(".StackOverflowCheck_End"); @@ -169,13 +169,13 @@ private void MethodBegin(Il2cpuMethodInfo aMethod) XS.Set(xName, 1, destinationIsIndirect: true, size: RegisterSize.Byte8); XS.Jump(".AfterCCTorAlreadyCalledCheck"); XS.Label(".BeforeQuickReturn"); - XS.Set(ECX, 0); + XS.Set(RCX, 0); XS.Return(); XS.Label(".AfterCCTorAlreadyCalledCheck"); } - XS.Push(EBP); - XS.Set(EBP, ESP); + XS.Push(RBP); + XS.Set(RBP, RSP); if (aMethod.MethodAssembler == null && aMethod.PlugMethod == null && !aMethod.IsInlineAssembler) { @@ -287,9 +287,10 @@ private void MethodEnd(Il2cpuMethodInfo aMethod) var xMethodLabel = ILOp.GetLabel(aMethod); XS.Label(xMethodLabel + EndOfMethodLabelNameNormal); XS.Comment("Following code is for debugging. Adjust accordingly!"); - XS.Set(AsmMarker.Labels[AsmMarker.Type.Int_LastKnownAddress], xMethodLabel + EndOfMethodLabelNameNormal, destinationIsIndirect: true); + XS.Set(R10, xMethodLabel + EndOfMethodLabelNameNormal, size: RegisterSize.Long64); + XS.Set(AsmMarker.Labels[AsmMarker.Type.Int_LastKnownAddress], R10, true); - XS.Set(ECX, 0); + XS.Set(RCX, 0); // Determine size of return value uint xReturnSize = 0; @@ -341,8 +342,8 @@ private void MethodEnd(Il2cpuMethodInfo aMethod) // move return value for (int i = 0; i < (int)(xReturnSize / 4); i++) { - XS.Pop(EAX); - XS.Set(EBP, EAX, destinationDisplacement: (int)(xOffset + (i + 0) * 4)); + XS.Pop(RAX); + XS.Set(RBP, RAX, destinationDisplacement: (int)(xOffset + (i + 0) * 4)); } } // extra stack space is the space reserved for example when a "public static int TestMethod();" method is called, 4 bytes is pushed, to make room for result; @@ -360,13 +361,13 @@ private void MethodEnd(Il2cpuMethodInfo aMethod) if (xLocalsSize >= 256) { - XS.Add(ESP, 255); + XS.Add(RSP, 255); xLocalsSize -= 255; } } if (xLocalsSize > 0) { - XS.Add(ESP, xLocalsSize); + XS.Add(RSP, xLocalsSize); } } @@ -374,28 +375,28 @@ private void MethodEnd(Il2cpuMethodInfo aMethod) { // if debugstub is active, emit a stack corruption detection. at this point EBP and ESP should have the same value. // if not, we should somehow break here. - XS.Set(EAX, ESP); - XS.Set(EBX, EBP); - XS.Compare(EAX, EBX); + XS.Set(RAX, RSP); + XS.Set(RBX, RBP); + XS.Compare(RAX, RBX); XS.Jump(ConditionalTestEnum.Equal, xLabelExc + "__2"); XS.ClearInterruptFlag(); // don't remove the call. It seems pointless, but we need it to retrieve the EIP value XS.Call(".MethodFooterStackCorruptionCheck_Break_on_location"); XS.Label(xLabelExc + ".MethodFooterStackCorruptionCheck_Break_on_location"); XS.Exchange(BX, BX); - XS.Pop(ECX); - XS.Push(EAX); - XS.Push(EBX); - XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], ECX, destinationIsIndirect: true); + XS.Pop(RCX); + XS.Push(RAX); + XS.Push(RBX); + XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], RCX, destinationIsIndirect: true); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendSimpleNumber]); - XS.Add(ESP, 4); + XS.Add(RSP, 4); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendSimpleNumber]); - XS.Add(ESP, 4); + XS.Add(RSP, 4); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendStackCorruptedEvent]); XS.Halt(); } XS.Label(xLabelExc + "__2"); - XS.Pop(EBP); + XS.Pop(RBP); var xRetSize = xTotalArgsSize - (int)xReturnSize; if (xRetSize < 0) { @@ -676,7 +677,7 @@ private void Call(Il2cpuMethodInfo aMethod, Il2cpuMethodInfo aTargetMethod, stri } if (xSize > 0) { - XS.Sub(ESP, xSize); + XS.Sub(RSP, xSize); } XS.Call(ILOp.GetLabel(aTargetMethod)); var xMethodInfo = aMethod.MethodBase as MethodInfo; @@ -697,7 +698,7 @@ private void Call(Il2cpuMethodInfo aMethod, Il2cpuMethodInfo aTargetMethod, stri } for (int i = 0; i < xResultSize / 4; i++) { - XS.Add(ESP, 4); + XS.Add(RSP, 4); } }, aNextLabel); } @@ -734,8 +735,8 @@ public unsafe void GenerateVMTCode(HashSet aTypesSet, HashSet { XS.Comment("---------------------------------------------------------"); XS.Label(InitVMTCodeLabel); - XS.Push(EBP); - XS.Set(EBP, ESP); + XS.Push(RBP); + XS.Set(RBP, RSP); var xTypesFieldRef = VTablesImplRefs.VTablesImplDef.GetField("mTypes", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance); string xTheName = LabelName.GetStaticFieldName(xTypesFieldRef); @@ -776,12 +777,14 @@ public unsafe void GenerateVMTCode(HashSet aTypesSet, HashSet byte[] xData = AllocateEmptyArray(aTypesSet.Count, (int)ILOp.SizeOfType(VTableType), xArrayTypeID); XS.DataMemberBytes(xTheName + "_Contents", xData); - XS.DataMember(xTheName, 1, "db", "0, 0, 0, 0, 0, 0, 0, 0"); - XS.Set(xTheName, xTheName + "_Contents", destinationIsIndirect: true, destinationDisplacement: 4); + XS.DataMember(xTheName, 1, "db", "0, 0, 0, 0, 0, 0, 0, 0"); + XS.Set(R10, xTheName + "_Contents", sourceIsIndirect: true); + XS.Set(xTheName, R10, destinationIsIndirect: true, destinationDisplacement: 4); xData = AllocateEmptyArray(aTypesSet.Count, (int)ILOp.SizeOfType(GCTableType), xArrayTypeID); XS.DataMemberBytes(xGCArrayName + "_Contents", xData); - XS.DataMember(xGCArrayName, 1, "db", "0, 0, 0, 0, 0, 0, 0, 0"); - XS.Set(xGCArrayName, xGCArrayName + "_Contents", destinationIsIndirect: true, destinationDisplacement: 4); + XS.DataMember(xGCArrayName, 1, "db", "0, 0, 0, 0, 0, 0, 0, 0"); + XS.Set(R10, xGCArrayName + "_Contents", sourceIsIndirect: true); + XS.Set(xGCArrayName, R10, destinationIsIndirect: true, destinationDisplacement: 4); #if VMT_DEBUG using (var xVmtDebugOutput = XmlWriter.Create( File.Create(Path.Combine(mLogDir, @"vmt_debug.xml")), new XmlWriterSettings() { Indent = true })) @@ -834,7 +837,7 @@ public unsafe void GenerateVMTCode(HashSet aTypesSet, HashSet // Type ID string xDataName = $"VMT__TYPE_ID_HOLDER__{xTypeName}"; XS.Comment(xType.FullName); - XS.Set(xDataName, (uint)xTypeID, destinationIsIndirect: true, size: RegisterSize.Int32); + XS.Set(xDataName, (uint)xTypeID, destinationIsIndirect: true, size: RegisterSize.Long64); XS.DataMember(xDataName, xTypeID); XS.Push(xTypeID); @@ -1022,7 +1025,7 @@ public unsafe void GenerateVMTCode(HashSet aTypesSet, HashSet #endif XS.Label("_END_OF_" + InitVMTCodeLabel); - XS.Pop(EBP); + XS.Pop(RBP); XS.Return(); } @@ -1220,7 +1223,7 @@ internal void GenerateMethodForward(Il2cpuMethodInfo aFrom, Il2cpuMethodInfo aTo if (xObjectPointerAccessAttrib != null) { XS.Comment("Skipping the reference to the next object reference."); - XS.Add(ESP, 4); + XS.Add(RSP, 4); xExtraSpaceToSkipDueToObjectPointerAccess += 4; } else @@ -1260,7 +1263,7 @@ internal void GenerateMethodForward(Il2cpuMethodInfo aFrom, Il2cpuMethodInfo aTo { xOriginalParamsIdx++; Ldarg(aFrom, xCurParamIdx + xCurParamOffset); - XS.Add(ESP, 4); + XS.Add(RSP, 4); xExtraSpaceToSkipDueToObjectPointerAccess += 4; xCurParamIdx++; } @@ -1304,11 +1307,12 @@ public void EmitEntrypoint(MethodBase aEntrypoint, MethodBase[] aBootEntries = n // at the time the datamembers for literal strings are created, the type id for string is not yet determined. // for now, we fix this at runtime. XS.Label(InitStringIDsLabel); - XS.Push(EBP); - XS.Set(EBP, ESP); - XS.Set(EAX, ILOp.GetTypeIDLabel(typeof(string)), sourceIsIndirect: true); + XS.Push(RBP); + XS.Set(RBP, RSP); + XS.Set(RAX, ILOp.GetTypeIDLabel(typeof(string)), sourceIsIndirect: true); + XS.Set(R10, LdStr.GetContentsArrayName(Assembler, "")); XS.Set(LabelName.GetStaticFieldName(typeof(string).GetField("Empty", BindingFlags.Static | BindingFlags.Public)), - LdStr.GetContentsArrayName(Assembler, ""), destinationDisplacement: 4); + R10, destinationDisplacement: 4); var xMemberId = 0; @@ -1330,12 +1334,12 @@ public void EmitEntrypoint(MethodBase aEntrypoint, MethodBase[] aBootEntries = n new Mov { DestinationRef = ElementReference.New(xDataMember.Name), DestinationIsIndirect = true, SourceReg = RegistersEnum.EAX }; } Assembler.WriteDebugVideo("Done"); - XS.Pop(EBP); + XS.Pop(RBP); XS.Return(); XS.Label(CosmosAssembler.EntryPointName); - XS.Push(EBP); - XS.Set(EBP, ESP); + XS.Push(RBP); + XS.Set(RBP, RSP); Assembler.WriteDebugVideo("Initializing VMT."); XS.Call(InitVMTCodeLabel); Assembler.WriteDebugVideo("Initializing string IDs."); @@ -1351,7 +1355,7 @@ public void EmitEntrypoint(MethodBase aEntrypoint, MethodBase[] aBootEntries = n XS.Label(xCurLabel); X86.IL.Call.DoExecute(Assembler, null, aEntrypoint.DeclaringType.GetMethod("Start"), null, xCurLabel, CosmosAssembler.EntryPointName + ".AfterStart", DebugEnabled); XS.Label(CosmosAssembler.EntryPointName + ".AfterStart"); - XS.Pop(EBP); + XS.Pop(RBP); XS.Return(); if (ShouldOptimize) @@ -1435,18 +1439,18 @@ private void BeforeOp(Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool emitInt3N // if debugstub is active, emit a stack corruption detection. at this point EBP and ESP should have the same value. // if not, we should somehow break here. - XS.Set(EAX, ESP); - XS.Set(EBX, EBP); + XS.Set(RAX, RSP); + XS.Set(RBX, RBP); if (xStackDifference != 0) { - XS.Add(EAX, xStackDifference.Value); + XS.Add(RAX, xStackDifference.Value); } - XS.Compare(EAX, EBX); + XS.Compare(RAX, RBX); XS.Jump(ConditionalTestEnum.Equal, xLabel + ".StackCorruptionCheck_End"); - XS.Push(EAX); - XS.Push(EBX); + XS.Push(RAX); + XS.Push(RBX); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendSimpleNumber]); - XS.Add(ESP, 4); + XS.Add(RSP, 4); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendSimpleNumber]); XS.ClearInterruptFlag(); @@ -1454,8 +1458,8 @@ private void BeforeOp(Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool emitInt3N XS.Call(xLabel + ".StackCorruptionCheck_GetAddress"); XS.Label(xLabel + ".StackCorruptionCheck_GetAddress"); XS.Exchange(BX, BX); - XS.Pop(EAX); - XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], EAX, destinationIsIndirect: true); + XS.Pop(RAX); + XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], RAX, destinationIsIndirect: true); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendStackCorruptedEvent]); XS.Halt(); XS.Label(xLabel + ".StackCorruptionCheck_End"); diff --git a/source/Cosmos.IL2CPU/CosmosAssembler.cs b/source/Cosmos.IL2CPU/CosmosAssembler.cs index 394bec59c..b70a80e2e 100644 --- a/source/Cosmos.IL2CPU/CosmosAssembler.cs +++ b/source/Cosmos.IL2CPU/CosmosAssembler.cs @@ -91,11 +91,11 @@ public void CreateGDT() DestinationDisplacement = 2, SourceRef = ElementReference.New("_NATIVE_GDT_Contents") }; - XS.Set(EAX, "_NATIVE_GDT_Pointer"); - XS.LoadGdt(EAX, isIndirect: true); + XS.Set(RAX, "_NATIVE_GDT_Pointer"); + XS.LoadGdt(RAX, isIndirect: true); XS.Comment("Set data segments"); - XS.Set(EAX, mGdData); + XS.Set(RAX, mGdData); XS.Set(DS, AX); XS.Set(ES, AX); XS.Set(FS, AX); @@ -115,7 +115,7 @@ public void CreateGDT() protected void SetIdtDescriptor(int aNo, string aLabel, bool aDisableInts) { int xOffset = aNo * 8; - XS.Set(EAX, aLabel); + XS.Set(RAX, aLabel); var xIDT = ElementReference.New("_NATIVE_IDT_Contents"); new Mov { @@ -131,7 +131,7 @@ protected void SetIdtDescriptor(int aNo, string aLabel, bool aDisableInts) DestinationDisplacement = xOffset + 1, SourceReg = RegistersEnum.AH }; - XS.ShiftRight(EAX, 16); + XS.ShiftRight(RAX, 16); new Mov { DestinationRef = xIDT, @@ -209,21 +209,23 @@ public void CreateIDT() DataMembers.Add(new DataMember("_NATIVE_IDT_Pointer", new ushort[] { xIdtSize, 0, 0 - })); + })); + + XS.Set(R10, "_NATIVE_IDT_Contents", sourceIsIndirect: true); new Mov { DestinationRef = ElementReference.New("_NATIVE_IDT_Pointer"), DestinationIsIndirect = true, DestinationDisplacement = 2, - SourceRef = ElementReference.New("_NATIVE_IDT_Contents") + SourceReg = R10 }; - XS.Set(EAX, "_NATIVE_IDT_Pointer"); + XS.Set(RAX, "_NATIVE_IDT_Pointer"); if (mComPort > 0) { XS.Set(AsmMarker.Labels[AsmMarker.Type.Processor_IntsEnabled], 1, destinationIsIndirect: true, size: RegisterSize.Byte8); - XS.LoadIdt(EAX, isIndirect: true); + XS.LoadIdt(RAX, isIndirect: true); } XS.Label("AfterCreateIDT"); new Comment(this, "END - Create IDT"); @@ -333,7 +335,7 @@ public void Initialize(bool enableVBE, string VBEResolution) // This is our first entry point. Multiboot uses this as Cosmos entry point. new Label("Kernel_Start", isGlobal: true); - XS.Set(ESP, "Kernel_Stack"); + XS.Set(RSP, "Kernel_Stack"); // Displays "Cosmos" in top left. Used to make sure Cosmos is booted in case of hang. // ie bootloader debugging. This must be the FIRST code, even before setup so we know @@ -368,7 +370,7 @@ public void Initialize(bool enableVBE, string VBEResolution) new Comment(this, "END - Multiboot Info"); new LiteralAssemblerCode("%endif"); WriteDebugVideo("Creating GDT."); - CreateGDT(); + //CreateGDT(); //limine creates the GDT for us WriteDebugVideo("Configuring PIC"); ConfigurePIC(); @@ -492,7 +494,7 @@ private void ConfigurePIC() Action xOutBytes = (port, value) => { XS.Set(DX, port); - XS.Set(EAX, value); + XS.Set(RAX, value); XS.WriteToPortDX(AL); }; @@ -591,16 +593,14 @@ protected byte[] GdtDescriptor(uint aBase, uint aSize, bool aCode) protected override void BeforeFlushText(TextWriter aOutput) { base.BeforeFlushText(aOutput); - aOutput.WriteLine("%ifndef ELF_COMPILATION"); - aOutput.WriteLine("use32"); - aOutput.WriteLine("org 0x1000000"); - aOutput.WriteLine("[map all main.map]"); - aOutput.WriteLine("%endif"); + aOutput.WriteLine("BITS 64"); + aOutput.WriteLine("section .data"); } - protected override void OnBeforeFlush() + protected override void OnBeforeFlush(TextWriter output) { - DataMembers.AddRange(new DataMember[] { new DataMember("_end_data", Array.Empty()) }); + DataMembers.AddRange(new DataMember[] { new DataMember("_end_data", Array.Empty()) }); + //output.WriteLine("section .text"); } protected override void OnFlushTextAfterEmitEverything(TextWriter aOutput) @@ -609,7 +609,7 @@ protected override void OnFlushTextAfterEmitEverything(TextWriter aOutput) aOutput.WriteLine("SystemExceptionOccurred:"); aOutput.WriteLine("\tret"); - aOutput.WriteLine("global Kernel_Start"); + //aOutput.WriteLine("global Kernel_Start"); aOutput.WriteLine("_end_code:"); } } diff --git a/source/Cosmos.IL2CPU/IL/Add.cs b/source/Cosmos.IL2CPU/IL/Add.cs index fd99f8280..1706be024 100644 --- a/source/Cosmos.IL2CPU/IL/Add.cs +++ b/source/Cosmos.IL2CPU/IL/Add.cs @@ -1,72 +1,72 @@ -using System; -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Add)] - public class Add : ILOp - { - public Add(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - var xIsFloat = TypeIsFloat(xType); - DoExecute(xSize, xIsFloat); - } - - public static void DoExecute(uint xSize, bool xIsFloat) - { - if (xSize > 8) - { - //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add.cs->Error: StackSize > 8 not supported"); - } - else - { - if (xSize > 4) - { - if (xIsFloat) // double - { - - // Please note that SSE supports double operations only from version 2 - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - // Move the stack of 8 bytes to get the second double - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.AddSD(XMM1, XMM0); - XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true); - } - else // long - { - XS.Pop(EDX); // low part - XS.Pop(EAX); // high part - XS.Add(ESP, EDX, destinationIsIndirect: true); - XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4); - } - } - else - { - if (xIsFloat) //float - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.AddSS(XMM1, XMM0); - XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true); - } - else //integer - { - XS.Pop(EAX); - XS.Add(ESP, EAX, destinationIsIndirect: true); - } - } - } - } - } -} +using System; +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Add)] + public class Add : ILOp + { + public Add(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + var xIsFloat = TypeIsFloat(xType); + DoExecute(xSize, xIsFloat); + } + + public static void DoExecute(uint xSize, bool xIsFloat) + { + if (xSize > 8) + { + //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add.cs->Error: StackSize > 8 not supported"); + } + else + { + if (xSize > 4) + { + if (xIsFloat) // double + { + + // Please note that SSE supports double operations only from version 2 + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + // Move the stack of 8 bytes to get the second double + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.AddSD(XMM1, XMM0); + XS.SSE2.MoveSD(RSP, XMM1, destinationIsIndirect: true); + } + else // long + { + XS.Pop(RDX); // low part + XS.Pop(RAX); // high part + XS.Add(RSP, RDX, destinationIsIndirect: true); + XS.AddWithCarry(RSP, RAX, destinationDisplacement: 4); + } + } + else + { + if (xIsFloat) //float + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.AddSS(XMM1, XMM0); + XS.SSE.MoveSS(RSP, XMM1, destinationIsIndirect: true); + } + else //integer + { + XS.Pop(RAX); + XS.Add(RSP, RAX, destinationIsIndirect: true); + } + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Add_Ovf.cs b/source/Cosmos.IL2CPU/IL/Add_Ovf.cs index 2f28c33f2..b5ac9eed3 100644 --- a/source/Cosmos.IL2CPU/IL/Add_Ovf.cs +++ b/source/Cosmos.IL2CPU/IL/Add_Ovf.cs @@ -1,68 +1,68 @@ -using System; -using XSharp.Assembler.x86; -using XSharp; -using static XSharp.XSRegisters; -using System.Reflection; - -/* Add.Ovf is signed integer addition with check for overflow */ -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Add_Ovf)] - public class Add_Ovf : ILOp - { - public Add_Ovf(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - var xIsFloat = TypeIsFloat(xType); - - if (xIsFloat) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: Expected signed integer operands but get float!"); - } - - if (xSize > 8) - { - //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: StackSize > 8 not supported"); - } - else - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - if (xSize > 4) // long - { - XS.Pop(EDX); // low part - XS.Pop(EAX); // high part - XS.Add(ESP, EDX, destinationIsIndirect: true); - XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4); - - } - else //integer - { - - XS.Pop(EAX); - XS.Add(ESP, EAX, destinationIsIndirect: true); - } - - // Let's check if we add overflow and if so throw OverflowException - XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel); - if (xSize > 4) // Hack to stop stack corruption - { - XS.Add(ESP, 8); - } - else - { - XS.Add(ESP, 4); - } - Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); - XS.Label(xSuccessLabel); - } - } - } -} +using System; +using XSharp.Assembler.x86; +using XSharp; +using static XSharp.XSRegisters; +using System.Reflection; + +/* Add.Ovf is signed integer addition with check for overflow */ +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Add_Ovf)] + public class Add_Ovf : ILOp + { + public Add_Ovf(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + var xIsFloat = TypeIsFloat(xType); + + if (xIsFloat) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: Expected signed integer operands but get float!"); + } + + if (xSize > 8) + { + //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf.cs->Error: StackSize > 8 not supported"); + } + else + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + if (xSize > 4) // long + { + XS.Pop(RDX); // low part + XS.Pop(RAX); // high part + XS.Add(RSP, RDX, destinationIsIndirect: true); + XS.AddWithCarry(RSP, RAX, destinationDisplacement: 4); + + } + else //integer + { + + XS.Pop(RAX); + XS.Add(RSP, RAX, destinationIsIndirect: true); + } + + // Let's check if we add overflow and if so throw OverflowException + XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel); + if (xSize > 4) // Hack to stop stack corruption + { + XS.Add(RSP, 8); + } + else + { + XS.Add(RSP, 4); + } + Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); + XS.Label(xSuccessLabel); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs b/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs index 7ac593fd3..9d4b1607c 100644 --- a/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs @@ -1,67 +1,67 @@ -using System; -using XSharp.Assembler.x86; -using XSharp; -using static XSharp.XSRegisters; -using System.Reflection; - -/* Add.Ovf is unsigned integer addition with check for overflow */ -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Add_Ovf_Un)] - public class Add_Ovf_Un : ILOp - { - public Add_Ovf_Un(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - // TODO overflow check for float - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - var xIsFloat = TypeIsFloat(xType); - - if (xIsFloat) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: Expected unsigned integer operands but get float!"); - } - - if (xSize > 8) - { - //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: StackSize > 8 not supported"); - } - else - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - if (xSize > 4) // long - { - XS.Pop(EDX); // low part - XS.Pop(EAX); // high part - XS.Add(ESP, EDX, destinationIsIndirect: true); - XS.AddWithCarry(ESP, EAX, destinationDisplacement: 4); - } - else //integer - { - XS.Pop(EAX); - XS.Add(ESP, EAX, destinationIsIndirect: true); - } - - // Let's check if we add overflow and if so throw OverflowException - XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); - if (xSize > 4) // Hack to stop stack corruption - { - XS.Add(ESP, 8); - } - else - { - XS.Add(ESP, 4); - } - Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); - XS.Label(xSuccessLabel); - } - } - } -} +using System; +using XSharp.Assembler.x86; +using XSharp; +using static XSharp.XSRegisters; +using System.Reflection; + +/* Add.Ovf is unsigned integer addition with check for overflow */ +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Add_Ovf_Un)] + public class Add_Ovf_Un : ILOp + { + public Add_Ovf_Un(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + // TODO overflow check for float + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + var xIsFloat = TypeIsFloat(xType); + + if (xIsFloat) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: Expected unsigned integer operands but get float!"); + } + + if (xSize > 8) + { + //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Add_Ovf_Un.cs->Error: StackSize > 8 not supported"); + } + else + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + if (xSize > 4) // long + { + XS.Pop(RDX); // low part + XS.Pop(RAX); // high part + XS.Add(RSP, RDX, destinationIsIndirect: true); + XS.AddWithCarry(RSP, RAX, destinationDisplacement: 4); + } + else //integer + { + XS.Pop(RAX); + XS.Add(RSP, RAX, destinationIsIndirect: true); + } + + // Let's check if we add overflow and if so throw OverflowException + XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); + if (xSize > 4) // Hack to stop stack corruption + { + XS.Add(RSP, 8); + } + else + { + XS.Add(RSP, 4); + } + Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); + XS.Label(xSuccessLabel); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/And.cs b/source/Cosmos.IL2CPU/IL/And.cs index 1226e8dca..eb6d92336 100644 --- a/source/Cosmos.IL2CPU/IL/And.cs +++ b/source/Cosmos.IL2CPU/IL/And.cs @@ -1,54 +1,54 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.And)] - public class And : ILOp - { - public And(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSize = SizeOfType(xStackContent); - var xStackContent2 = aOpCode.StackPopTypes[1]; - var xStackContent2Size = SizeOfType(xStackContent2); - - var xSize = Math.Max(xStackContentSize, xStackContent2Size); - if (Align(xStackContentSize, 4) != Align(xStackContent2Size, 4)) - { - throw new NotSupportedException("Cosmos.IL2CPU.x86->IL->And.cs->Error: Operands have different size!"); - } - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->And.cs->Error: StackSize > 8 not supported"); - } - - if (xSize > 4) - { - // [ESP] is low part - // [ESP + 4] is high part - // [ESP + 8] is low part - // [ESP + 12] is high part - XS.Pop(EAX); - XS.Pop(EDX); - // [ESP] is low part - // [ESP + 4] is high part - XS.And(ESP, EAX, destinationIsIndirect: true); - XS.And(ESP, EDX, destinationDisplacement: 4); - } - else - { - XS.Pop(EAX); - XS.And(ESP, EAX, destinationIsIndirect: true); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.And)] + public class And : ILOp + { + public And(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSize = SizeOfType(xStackContent); + var xStackContent2 = aOpCode.StackPopTypes[1]; + var xStackContent2Size = SizeOfType(xStackContent2); + + var xSize = Math.Max(xStackContentSize, xStackContent2Size); + if (Align(xStackContentSize, 4) != Align(xStackContent2Size, 4)) + { + throw new NotSupportedException("Cosmos.IL2CPU.x86->IL->And.cs->Error: Operands have different size!"); + } + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->And.cs->Error: StackSize > 8 not supported"); + } + + if (xSize > 4) + { + // [ESP] is low part + // [ESP + 4] is high part + // [ESP + 8] is low part + // [ESP + 12] is high part + XS.Pop(RAX); + XS.Pop(RDX); + // [ESP] is low part + // [ESP + 4] is high part + XS.And(RSP, RAX, destinationIsIndirect: true); + XS.And(RSP, RDX, destinationDisplacement: 4); + } + else + { + XS.Pop(RAX); + XS.And(RSP, RAX, destinationIsIndirect: true); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Box.cs b/source/Cosmos.IL2CPU/IL/Box.cs index 4f42eb4e4..d1ea8a908 100644 --- a/source/Cosmos.IL2CPU/IL/Box.cs +++ b/source/Cosmos.IL2CPU/IL/Box.cs @@ -1,45 +1,45 @@ -using Cosmos.IL2CPU.ILOpCodes; -using IL2CPU.API; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Box)] - public class Box : ILOp - { - public Box(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = (OpType)aOpCode; - - if (IsReferenceType(xType.Value)) - { - return; - } - - uint xSize = Align(SizeOfType(xType.Value), 4); - string xTypeID = GetTypeIDLabel(xType.Value); - - XS.Push(ObjectUtils.FieldDataOffset + xSize); - XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); - XS.Pop(ESI); - XS.Set(EBX, xTypeID, sourceIsIndirect: true); - XS.Set(ESI, EBX, destinationIsIndirect: true); - XS.Set(ESI, (uint)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationDisplacement: 4, size: RegisterSize.Int32); - new Comment(Assembler, "xSize is " + xSize); - for (int i = 0; i < xSize / 4; i++) - { - XS.Pop(EDX); - XS.Set(ESI, EDX, destinationDisplacement: ObjectUtils.FieldDataOffset + i * 4, size: RegisterSize.Int32); - } - XS.Push(ESI); - XS.Push(0); - } - } -} +using Cosmos.IL2CPU.ILOpCodes; +using IL2CPU.API; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Box)] + public class Box : ILOp + { + public Box(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = (OpType)aOpCode; + + if (IsReferenceType(xType.Value)) + { + return; + } + + uint xSize = Align(SizeOfType(xType.Value), 4); + string xTypeID = GetTypeIDLabel(xType.Value); + + XS.Push(ObjectUtils.FieldDataOffset + xSize); + XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); + XS.Pop(RSI); + XS.Set(RBX, xTypeID, sourceIsIndirect: true); + XS.Set(RSI, RBX, destinationIsIndirect: true); + XS.Set(RSI, (uint)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationDisplacement: 4, size: RegisterSize.Long64); + new Comment(Assembler, "xSize is " + xSize); + for (int i = 0; i < xSize / 4; i++) + { + XS.Pop(RDX); + XS.Set(RSI, RDX, destinationDisplacement: ObjectUtils.FieldDataOffset + i * 4, size: RegisterSize.Long64); + } + XS.Push(RSI); + XS.Push(0); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Branch.cs b/source/Cosmos.IL2CPU/IL/Branch.cs index d6729d2e3..3c5a12035 100644 --- a/source/Cosmos.IL2CPU/IL/Branch.cs +++ b/source/Cosmos.IL2CPU/IL/Branch.cs @@ -1,247 +1,247 @@ -using System; -using System.Collections.Generic; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using XSharp.Assembler.x86.SSE; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Beq)] - [OpCode(ILOpCode.Code.Bge)] - [OpCode(ILOpCode.Code.Bgt)] - [OpCode(ILOpCode.Code.Ble)] - [OpCode(ILOpCode.Code.Blt)] - [OpCode(ILOpCode.Code.Bne_Un)] - [OpCode(ILOpCode.Code.Bge_Un)] - [OpCode(ILOpCode.Code.Bgt_Un)] - [OpCode(ILOpCode.Code.Ble_Un)] - [OpCode(ILOpCode.Code.Blt_Un)] - [OpCode(ILOpCode.Code.Brfalse)] - [OpCode(ILOpCode.Code.Brtrue)] - public class Branch : ILOp - { - private static readonly Dictionary TestOPs = new Dictionary() - { - [ILOpCode.Code.Beq] = ConditionalTestEnum.Equal, - [ILOpCode.Code.Bge] = ConditionalTestEnum.GreaterThanOrEqualTo, - [ILOpCode.Code.Bgt] = ConditionalTestEnum.GreaterThan, - [ILOpCode.Code.Ble] = ConditionalTestEnum.LessThanOrEqualTo, - [ILOpCode.Code.Blt] = ConditionalTestEnum.LessThan, - [ILOpCode.Code.Bne_Un] = ConditionalTestEnum.NotEqual, - [ILOpCode.Code.Bge_Un] = ConditionalTestEnum.AboveOrEqual, - [ILOpCode.Code.Bgt_Un] = ConditionalTestEnum.Above, - [ILOpCode.Code.Ble_Un] = ConditionalTestEnum.BelowOrEqual, - [ILOpCode.Code.Blt_Un] = ConditionalTestEnum.Below - }; - - private static readonly Dictionary SseCompareOPs = new Dictionary() - { - [ILOpCode.Code.Beq] = ComparePseudoOpcodes.Equal, - [ILOpCode.Code.Bge] = ComparePseudoOpcodes.NotLessThan, - [ILOpCode.Code.Bgt] = ComparePseudoOpcodes.NotLessThanOrEqualTo, - [ILOpCode.Code.Ble] = ComparePseudoOpcodes.LessThanOrEqualTo, - [ILOpCode.Code.Blt] = ComparePseudoOpcodes.LessThan, - [ILOpCode.Code.Bne_Un] = ComparePseudoOpcodes.NotEqual, - [ILOpCode.Code.Bge_Un] = ComparePseudoOpcodes.NotLessThan, - [ILOpCode.Code.Bgt_Un] = ComparePseudoOpcodes.NotLessThanOrEqualTo, - [ILOpCode.Code.Ble_Un] = ComparePseudoOpcodes.LessThanOrEqualTo, - [ILOpCode.Code.Blt_Un] = ComparePseudoOpcodes.LessThan - }; - - public Branch(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOp = aOpCode.OpCode; - var xBranchLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode); - - var xStackType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xStackType); - var xIsFloat = TypeIsFloat(xStackType); - - if (xOp == ILOpCode.Code.Brtrue - || xOp == ILOpCode.Code.Brfalse) - { - if (xIsFloat) - { - throw new NotSupportedException(); - } - - if (xSize <= 4) - { - XS.Pop(EAX); - XS.Compare(EAX, 0); - XS.Jump(xOp == ILOpCode.Code.Brtrue ? ConditionalTestEnum.NotEqual : ConditionalTestEnum.Equal, xBranchLabel); - } - else if (xSize <= 8) - { - XS.Pop(EAX); - XS.Pop(EBX); - - if (xOp == ILOpCode.Code.Brtrue) - { - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); - - XS.Compare(EBX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); - } - else - { - var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; - - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); - - XS.Compare(EBX, 0); - XS.Jump(ConditionalTestEnum.Equal, xBranchLabel); - - XS.Label(xEndLabel); - } - } - else if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); - } - - return; - } - - if (xIsFloat) - { - var xTestOp = SseCompareOPs[xOp]; - var xIsUnordered = xOp == ILOpCode.Code.Bge_Un - || xOp == ILOpCode.Code.Bgt_Un - || xOp == ILOpCode.Code.Ble_Un - || xOp == ILOpCode.Code.Blt_Un - || xOp == ILOpCode.Code.Bne_Un; - - if (xSize <= 4) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - - if (xIsUnordered) - { - XS.SSE.MoveSS(XMM2, XMM1); - XS.SSE.CompareSS(XMM2, XMM0, ComparePseudoOpcodes.Unordered); - XS.MoveD(EAX, XMM2); - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); - } - - XS.SSE.CompareSS(XMM1, XMM0, xTestOp); - XS.MoveD(EAX, XMM1); - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); - } - else if (xSize <= 8) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.Add(ESP, 8); - - if (xIsUnordered) - { - XS.SSE2.MoveSD(XMM2, XMM1); - XS.SSE2.CompareSD(XMM2, XMM0, ComparePseudoOpcodes.Unordered); - XS.MoveD(EAX, XMM2); - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); - } - - XS.SSE2.CompareSD(XMM1, XMM0, xTestOp); - XS.MoveD(EAX, XMM1); - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); - } - } - else - { - var xTestOp = TestOPs[xOp]; - - if (xSize <= 4) - { - XS.Pop(EAX); - XS.Pop(EBX); - XS.Compare(EBX, EAX); - XS.Jump(xTestOp, xBranchLabel); - } - else if (xSize <= 8) - { - var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; - - XS.Pop(EAX); - XS.Pop(EDX); - - XS.Pop(EBX); - XS.Pop(ECX); - - switch (xOp) - { - case ILOpCode.Code.Beq: - case ILOpCode.Code.Bne_Un: - XS.Compare(ECX, EDX); - XS.Jump(ConditionalTestEnum.NotEqual, xOp == ILOpCode.Code.Beq ? xEndLabel : xBranchLabel); - XS.Compare(EBX, EAX); - XS.Jump(xTestOp, xBranchLabel); - - break; - case ILOpCode.Code.Bge: - case ILOpCode.Code.Bgt: - XS.Compare(ECX, EDX); - XS.Jump(ConditionalTestEnum.GreaterThan, xBranchLabel); - XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); - XS.Compare(EBX, EAX); - XS.Jump(xTestOp, xBranchLabel); - - break; - case ILOpCode.Code.Ble: - case ILOpCode.Code.Blt: - XS.Compare(ECX, EDX); - XS.Jump(ConditionalTestEnum.LessThan, xBranchLabel); - XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); - XS.Compare(EBX, EAX); - XS.Jump(xTestOp, xBranchLabel); - - break; - case ILOpCode.Code.Bge_Un: - case ILOpCode.Code.Bgt_Un: - XS.Compare(ECX, EDX); - XS.Jump(ConditionalTestEnum.Above, xBranchLabel); - XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); - XS.Compare(EBX, EAX); - XS.Jump(xTestOp, xBranchLabel); - - break; - case ILOpCode.Code.Ble_Un: - case ILOpCode.Code.Blt_Un: - XS.Compare(ECX, EDX); - XS.Jump(ConditionalTestEnum.Below, xBranchLabel); - XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); - XS.Compare(EBX, EAX); - XS.Jump(xTestOp, xBranchLabel); - - break; - } - - XS.Label(xEndLabel); - } - } - - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; +using System.Collections.Generic; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using XSharp.Assembler.x86.SSE; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Beq)] + [OpCode(ILOpCode.Code.Bge)] + [OpCode(ILOpCode.Code.Bgt)] + [OpCode(ILOpCode.Code.Ble)] + [OpCode(ILOpCode.Code.Blt)] + [OpCode(ILOpCode.Code.Bne_Un)] + [OpCode(ILOpCode.Code.Bge_Un)] + [OpCode(ILOpCode.Code.Bgt_Un)] + [OpCode(ILOpCode.Code.Ble_Un)] + [OpCode(ILOpCode.Code.Blt_Un)] + [OpCode(ILOpCode.Code.Brfalse)] + [OpCode(ILOpCode.Code.Brtrue)] + public class Branch : ILOp + { + private static readonly Dictionary TestOPs = new Dictionary() + { + [ILOpCode.Code.Beq] = ConditionalTestEnum.Equal, + [ILOpCode.Code.Bge] = ConditionalTestEnum.GreaterThanOrEqualTo, + [ILOpCode.Code.Bgt] = ConditionalTestEnum.GreaterThan, + [ILOpCode.Code.Ble] = ConditionalTestEnum.LessThanOrEqualTo, + [ILOpCode.Code.Blt] = ConditionalTestEnum.LessThan, + [ILOpCode.Code.Bne_Un] = ConditionalTestEnum.NotEqual, + [ILOpCode.Code.Bge_Un] = ConditionalTestEnum.AboveOrEqual, + [ILOpCode.Code.Bgt_Un] = ConditionalTestEnum.Above, + [ILOpCode.Code.Ble_Un] = ConditionalTestEnum.BelowOrEqual, + [ILOpCode.Code.Blt_Un] = ConditionalTestEnum.Below + }; + + private static readonly Dictionary SseCompareOPs = new Dictionary() + { + [ILOpCode.Code.Beq] = ComparePseudoOpcodes.Equal, + [ILOpCode.Code.Bge] = ComparePseudoOpcodes.NotLessThan, + [ILOpCode.Code.Bgt] = ComparePseudoOpcodes.NotLessThanOrEqualTo, + [ILOpCode.Code.Ble] = ComparePseudoOpcodes.LessThanOrEqualTo, + [ILOpCode.Code.Blt] = ComparePseudoOpcodes.LessThan, + [ILOpCode.Code.Bne_Un] = ComparePseudoOpcodes.NotEqual, + [ILOpCode.Code.Bge_Un] = ComparePseudoOpcodes.NotLessThan, + [ILOpCode.Code.Bgt_Un] = ComparePseudoOpcodes.NotLessThanOrEqualTo, + [ILOpCode.Code.Ble_Un] = ComparePseudoOpcodes.LessThanOrEqualTo, + [ILOpCode.Code.Blt_Un] = ComparePseudoOpcodes.LessThan + }; + + public Branch(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOp = aOpCode.OpCode; + var xBranchLabel = AppAssembler.TmpBranchLabel(aMethod, aOpCode); + + var xStackType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xStackType); + var xIsFloat = TypeIsFloat(xStackType); + + if (xOp == ILOpCode.Code.Brtrue + || xOp == ILOpCode.Code.Brfalse) + { + if (xIsFloat) + { + throw new NotSupportedException(); + } + + if (xSize <= 4) + { + XS.Pop(RAX); + XS.Compare(RAX, 0); + XS.Jump(xOp == ILOpCode.Code.Brtrue ? ConditionalTestEnum.NotEqual : ConditionalTestEnum.Equal, xBranchLabel); + } + else if (xSize <= 8) + { + XS.Pop(RAX); + XS.Pop(RBX); + + if (xOp == ILOpCode.Code.Brtrue) + { + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); + + XS.Compare(RBX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); + } + else + { + var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; + + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); + + XS.Compare(RBX, 0); + XS.Jump(ConditionalTestEnum.Equal, xBranchLabel); + + XS.Label(xEndLabel); + } + } + else if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); + } + + return; + } + + if (xIsFloat) + { + var xTestOp = SseCompareOPs[xOp]; + var xIsUnordered = xOp == ILOpCode.Code.Bge_Un + || xOp == ILOpCode.Code.Bgt_Un + || xOp == ILOpCode.Code.Ble_Un + || xOp == ILOpCode.Code.Blt_Un + || xOp == ILOpCode.Code.Bne_Un; + + if (xSize <= 4) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + + if (xIsUnordered) + { + XS.SSE.MoveSS(XMM2, XMM1); + XS.SSE.CompareSS(XMM2, XMM0, ComparePseudoOpcodes.Unordered); + XS.MoveD(RAX, XMM2); + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); + } + + XS.SSE.CompareSS(XMM1, XMM0, xTestOp); + XS.MoveD(RAX, XMM1); + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); + } + else if (xSize <= 8) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.Add(RSP, 8); + + if (xIsUnordered) + { + XS.SSE2.MoveSD(XMM2, XMM1); + XS.SSE2.CompareSD(XMM2, XMM0, ComparePseudoOpcodes.Unordered); + XS.MoveD(RAX, XMM2); + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); + } + + XS.SSE2.CompareSD(XMM1, XMM0, xTestOp); + XS.MoveD(RAX, XMM1); + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xBranchLabel); + } + } + else + { + var xTestOp = TestOPs[xOp]; + + if (xSize <= 4) + { + XS.Pop(RAX); + XS.Pop(RBX); + XS.Compare(RBX, RAX); + XS.Jump(xTestOp, xBranchLabel); + } + else if (xSize <= 8) + { + var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; + + XS.Pop(RAX); + XS.Pop(RDX); + + XS.Pop(RBX); + XS.Pop(RCX); + + switch (xOp) + { + case ILOpCode.Code.Beq: + case ILOpCode.Code.Bne_Un: + XS.Compare(RCX, RDX); + XS.Jump(ConditionalTestEnum.NotEqual, xOp == ILOpCode.Code.Beq ? xEndLabel : xBranchLabel); + XS.Compare(RBX, RAX); + XS.Jump(xTestOp, xBranchLabel); + + break; + case ILOpCode.Code.Bge: + case ILOpCode.Code.Bgt: + XS.Compare(RCX, RDX); + XS.Jump(ConditionalTestEnum.GreaterThan, xBranchLabel); + XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); + XS.Compare(RBX, RAX); + XS.Jump(xTestOp, xBranchLabel); + + break; + case ILOpCode.Code.Ble: + case ILOpCode.Code.Blt: + XS.Compare(RCX, RDX); + XS.Jump(ConditionalTestEnum.LessThan, xBranchLabel); + XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); + XS.Compare(RBX, RAX); + XS.Jump(xTestOp, xBranchLabel); + + break; + case ILOpCode.Code.Bge_Un: + case ILOpCode.Code.Bgt_Un: + XS.Compare(RCX, RDX); + XS.Jump(ConditionalTestEnum.Above, xBranchLabel); + XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); + XS.Compare(RBX, RAX); + XS.Jump(xTestOp, xBranchLabel); + + break; + case ILOpCode.Code.Ble_Un: + case ILOpCode.Code.Blt_Un: + XS.Compare(RCX, RDX); + XS.Jump(ConditionalTestEnum.Below, xBranchLabel); + XS.Jump(ConditionalTestEnum.NotEqual, xEndLabel); + XS.Compare(RBX, RAX); + XS.Jump(xTestOp, xBranchLabel); + + break; + } + + XS.Label(xEndLabel); + } + } + + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Branch.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Call.cs b/source/Cosmos.IL2CPU/IL/Call.cs index 1a3196466..d9a6e73ec 100644 --- a/source/Cosmos.IL2CPU/IL/Call.cs +++ b/source/Cosmos.IL2CPU/IL/Call.cs @@ -1,159 +1,159 @@ -using System; -using System.Reflection; - -using IL2CPU.API; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Call)] - public class Call : ILOp - { - public Call(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public static uint GetStackSizeToReservate(MethodBase aMethod, Type aType = null) - { - var xMethodInfo = aMethod as MethodInfo; - uint xReturnSize = 0; - if (xMethodInfo != null) - { - xReturnSize = SizeOfType(xMethodInfo.ReturnType); - } - if (xReturnSize == 0) - { - return 0; - } - - // todo: implement exception support - int xExtraStackSize = (int)Align(xReturnSize, 4); - var xParameters = aMethod.GetParameters(); - foreach (var xItem in xParameters) - { - xExtraStackSize -= (int)Align(SizeOfType(xItem.ParameterType), 4); - } - if (!xMethodInfo.IsStatic) - { - if (aType != null) - { - if (IsReferenceType(aType)) - { - xExtraStackSize -= GetObjectReferenceSize(); - } - else - { - xExtraStackSize -= 4; - } - } - else - { - if (IsReferenceType(aMethod.DeclaringType)) - { - xExtraStackSize -= GetObjectReferenceSize(); - } - else - { - xExtraStackSize -= 4; - } - } - } - - if (xExtraStackSize > 0) - { - return (uint)xExtraStackSize; - } - return 0; - } - - private static int GetObjectReferenceSize() - { - // old code, which goof up everything for structs - //return (int)Align(SizeOfType(xMethodInfo.DeclaringType), 4); - // TODO native pointer size, so that COSMOS could be 64 bit OS - return 8; - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpMethod = aOpCode as OpMethod; - DoExecute(Assembler, aMethod, xOpMethod.Value, aOpCode, LabelName.Get(aMethod.MethodBase), DebugEnabled); - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, bool debugEnabled) - { - DoExecute(Assembler, aCurrentMethod, aTargetMethod, aCurrent, currentLabel, ILOp.GetLabel(aCurrentMethod, aCurrent.NextPosition), debugEnabled); - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aOp, string currentLabel, string nextLabel, bool debugEnabled) - { - var xMethodInfo = aTargetMethod as MethodInfo; - string xNormalAddress = LabelName.Get(aTargetMethod); - if (PlugManager.DirectPlugMapping.ContainsKey(LabelName.GetFullName(aTargetMethod))) - { - string xPlugAddress = LabelName.Get(PlugManager.DirectPlugMapping[LabelName.GetFullName(aTargetMethod)]); - XS.Comment($"Redirecting call to {xNormalAddress} directly to plug {xPlugAddress}"); - xNormalAddress = xPlugAddress; - } - var xParameters = aTargetMethod.GetParameters(); - - // todo: implement exception support - uint xExtraStackSize = GetStackSizeToReservate(aTargetMethod); - if (!aTargetMethod.IsStatic) - { - uint xThisOffset = 0; - foreach (var xItem in xParameters) - { - xThisOffset += Align(SizeOfType(xItem.ParameterType), 4); - } - var stackOffsetToCheck = xThisOffset; - if (IsReferenceType(aTargetMethod.DeclaringType)) - { - DoNullReferenceCheck(Assembler, debugEnabled, (int)stackOffsetToCheck + 4); - } - else - { - DoNullReferenceCheck(Assembler, debugEnabled, (int)stackOffsetToCheck); - } - } - - if (xExtraStackSize > 0) - { - XS.Sub(XSRegisters.ESP, xExtraStackSize); - } - XS.Call(xNormalAddress); - - if (aCurrentMethod != null) - { - uint xReturnSize = 0; - if (xMethodInfo != null) - { - xReturnSize = SizeOfType(xMethodInfo.ReturnType); - } - EmitExceptionLogic(Assembler, aCurrentMethod, aOp, true, - delegate - { - var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value; - - uint xPopSize = 0; - foreach (var type in aOp.StackPopTypes) - { - xPopSize += Align(SizeOfType(type), 4); - } - - var xResultSize = xReturnSize; - if (xResultSize % 4 != 0) - { - xResultSize += 4 - xResultSize % 4; - } - - ILOp.EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize); - }, nextLabel); - - } - } - } -} +using System; +using System.Reflection; + +using IL2CPU.API; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Call)] + public class Call : ILOp + { + public Call(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public static uint GetStackSizeToReservate(MethodBase aMethod, Type aType = null) + { + var xMethodInfo = aMethod as MethodInfo; + uint xReturnSize = 0; + if (xMethodInfo != null) + { + xReturnSize = SizeOfType(xMethodInfo.ReturnType); + } + if (xReturnSize == 0) + { + return 0; + } + + // todo: implement exception support + int xExtraStackSize = (int)Align(xReturnSize, 4); + var xParameters = aMethod.GetParameters(); + foreach (var xItem in xParameters) + { + xExtraStackSize -= (int)Align(SizeOfType(xItem.ParameterType), 4); + } + if (!xMethodInfo.IsStatic) + { + if (aType != null) + { + if (IsReferenceType(aType)) + { + xExtraStackSize -= GetObjectReferenceSize(); + } + else + { + xExtraStackSize -= 4; + } + } + else + { + if (IsReferenceType(aMethod.DeclaringType)) + { + xExtraStackSize -= GetObjectReferenceSize(); + } + else + { + xExtraStackSize -= 4; + } + } + } + + if (xExtraStackSize > 0) + { + return (uint)xExtraStackSize; + } + return 0; + } + + private static int GetObjectReferenceSize() + { + // old code, which goof up everything for structs + //return (int)Align(SizeOfType(xMethodInfo.DeclaringType), 4); + // TODO native pointer size, so that COSMOS could be 64 bit OS + return 8; + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpMethod = aOpCode as OpMethod; + DoExecute(Assembler, aMethod, xOpMethod.Value, aOpCode, LabelName.Get(aMethod.MethodBase), DebugEnabled); + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aCurrent, string currentLabel, bool debugEnabled) + { + DoExecute(Assembler, aCurrentMethod, aTargetMethod, aCurrent, currentLabel, ILOp.GetLabel(aCurrentMethod, aCurrent.NextPosition), debugEnabled); + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aCurrentMethod, MethodBase aTargetMethod, ILOpCode aOp, string currentLabel, string nextLabel, bool debugEnabled) + { + var xMethodInfo = aTargetMethod as MethodInfo; + string xNormalAddress = LabelName.Get(aTargetMethod); + if (PlugManager.DirectPlugMapping.ContainsKey(LabelName.GetFullName(aTargetMethod))) + { + string xPlugAddress = LabelName.Get(PlugManager.DirectPlugMapping[LabelName.GetFullName(aTargetMethod)]); + XS.Comment($"Redirecting call to {xNormalAddress} directly to plug {xPlugAddress}"); + xNormalAddress = xPlugAddress; + } + var xParameters = aTargetMethod.GetParameters(); + + // todo: implement exception support + uint xExtraStackSize = GetStackSizeToReservate(aTargetMethod); + if (!aTargetMethod.IsStatic) + { + uint xThisOffset = 0; + foreach (var xItem in xParameters) + { + xThisOffset += Align(SizeOfType(xItem.ParameterType), 4); + } + var stackOffsetToCheck = xThisOffset; + if (IsReferenceType(aTargetMethod.DeclaringType)) + { + DoNullReferenceCheck(Assembler, debugEnabled, (int)stackOffsetToCheck + 4); + } + else + { + DoNullReferenceCheck(Assembler, debugEnabled, (int)stackOffsetToCheck); + } + } + + if (xExtraStackSize > 0) + { + XS.Sub(XSRegisters.RSP, xExtraStackSize); + } + XS.Call(xNormalAddress); + + if (aCurrentMethod != null) + { + uint xReturnSize = 0; + if (xMethodInfo != null) + { + xReturnSize = SizeOfType(xMethodInfo.ReturnType); + } + EmitExceptionLogic(Assembler, aCurrentMethod, aOp, true, + delegate + { + var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value; + + uint xPopSize = 0; + foreach (var type in aOp.StackPopTypes) + { + xPopSize += Align(SizeOfType(type), 4); + } + + var xResultSize = xReturnSize; + if (xResultSize % 4 != 0) + { + xResultSize += 4 - xResultSize % 4; + } + + ILOp.EmitExceptionCleanupAfterCall(Assembler, xResultSize, xStackOffsetBefore, xPopSize); + }, nextLabel); + + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Calli.cs b/source/Cosmos.IL2CPU/IL/Calli.cs index 4eae30830..39e8b7cf9 100644 --- a/source/Cosmos.IL2CPU/IL/Calli.cs +++ b/source/Cosmos.IL2CPU/IL/Calli.cs @@ -1,22 +1,22 @@ -using System; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Calli)] - public class Calli : ILOp - { - public Calli(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - XS.Pop(EAX); - XS.Call(EAX); - } - } -} +using System; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Calli)] + public class Calli : ILOp + { + public Calli(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + XS.Pop(RAX); + XS.Call(RAX); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Callvirt.cs b/source/Cosmos.IL2CPU/IL/Callvirt.cs index f301a9c8c..48f50e428 100644 --- a/source/Cosmos.IL2CPU/IL/Callvirt.cs +++ b/source/Cosmos.IL2CPU/IL/Callvirt.cs @@ -1,271 +1,271 @@ -using System; -using System.Linq; -using System.Reflection; - -using Cosmos.IL2CPU.ILOpCodes; - -using IL2CPU.API; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; -using CPU = XSharp.Assembler.x86; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Callvirt)] - public class Callvirt : ILOp - { - public Callvirt(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpMethod = aOpCode as OpMethod; - DoExecute(Assembler, aMethod, xOpMethod.Value, xOpMethod.ValueUID, aOpCode, DebugEnabled); - } - - public static void DoExecute(Assembler aAssembler, Il2cpuMethodInfo aMethod, MethodBase aTargetMethod, uint aTargetMethodUID, ILOpCode aOp, bool aDebugEnabled) - { - string xCurrentMethodLabel = GetLabel(aMethod, aOp.Position); - Type xPopType = aOp.StackPopTypes.Last(); - var isInterface = aTargetMethod.DeclaringType.IsInterface; - - string xNormalAddress = ""; - if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal) - { - xNormalAddress = LabelName.Get(aTargetMethod); - } - - uint xReturnSize = 0; - var xMethodInfo = aTargetMethod as MethodInfo; - if (xMethodInfo != null) - { - xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4); - } - - var xExtraStackSize = Call.GetStackSizeToReservate(aTargetMethod, xPopType); - int xThisOffset = 0; - var xParameters = aTargetMethod.GetParameters(); - foreach (var xItem in xParameters) - { - xThisOffset += (int)Align(SizeOfType(xItem.ParameterType), 4); - } - - // This is finding offset to self? It looks like we dont need offsets of other - // arguments, but only self. If so can calculate without calculating all fields - // Might have to go to old data structure for the offset... - // Can we add this method info somehow to the data passed in? - // mThisOffset = mTargetMethodInfo.Arguments[0].Offset; - XS.Comment($"Calling = {aTargetMethod.DeclaringType.FullName}.{aTargetMethod.Name}"); - XS.Comment("ThisOffset = " + xThisOffset); - - if (IsReferenceType(xPopType)) - { - DoNullReferenceCheck(aAssembler, aDebugEnabled, xThisOffset + 4); - } - else - { - DoNullReferenceCheck(aAssembler, aDebugEnabled, xThisOffset); - } - - if (!String.IsNullOrEmpty(xNormalAddress)) - { - if (xExtraStackSize > 0) - { - XS.Sub(ESP, xExtraStackSize); - } - - XS.Call(xNormalAddress); - } - else - { - var afterCall = xCurrentMethodLabel + ".AfterCall"; - - /* - * On the stack now: - * $esp Params - * $esp + xThisOffset This - */ - if (xPopType.IsPointer || xPopType.IsByRef) - { - xPopType = xPopType.GetElementType(); - XS.Push(GetTypeIDLabel(xPopType), isIndirect: true); - } - else - { - XS.Set(EAX, ESP, sourceDisplacement: xThisOffset + 4); - XS.Set(EBX, EAX, sourceDisplacement: 4, sourceIsIndirect: true); // type of object - XS.Push(EAX, isIndirect: true); - } - - // To handle generic interfaces on arrays, we need to check if the callvirt is for such an interface, in which case if the object - // the method is being called on is an array, we dont push the type array but rather an typed array (System.Array vs T[]) - - if (aTargetMethod.DeclaringType.IsGenericType - && new string[] { "IList", "ICollection", "IEnumerable", "IReadOnlyList", "IReadOnlyCollection" } - .Any(i => aTargetMethod.DeclaringType.Name.Contains(i))) - { - isInterface = true; - var notArrayLabel = xCurrentMethodLabel + ".NotArrayType"; - var endOfCheckLabel = xCurrentMethodLabel + ".AfterGenericArrayInterfaceCheck"; - XS.Pop(EAX); // EAX now contains type of object - // Now check if type derives from array - XS.Compare(EBX, (uint)ObjectUtils.InstanceTypeEnum.Array); - XS.Jump(CPU.ConditionalTestEnum.NotEqual, notArrayLabel); - XS.Comment($"Set type to be {aTargetMethod.DeclaringType.GenericTypeArguments[0].MakeArrayType().Name}"); - XS.Push(GetTypeIDLabel(aTargetMethod.DeclaringType.GenericTypeArguments[0].MakeArrayType()), isIndirect: true); - XS.Jump(endOfCheckLabel); - XS.Label(notArrayLabel); // we already pushed that value when it does not need to be overwritten - XS.Push(EAX); - XS.Label(endOfCheckLabel); - } - - XS.Push(aTargetMethodUID); - - if (isInterface) - { - XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForInterfaceTypeRef)); - } - else - { - XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef)); - } - - if (xExtraStackSize > 0) - { - xThisOffset -= (int)xExtraStackSize; - } - - /* - * On the stack now: - * $esp Params - * $esp + xThisOffset This - */ - XS.Pop(ECX); - - XS.Label(xCurrentMethodLabel + ".AfterAddressCheck"); - - if (IsReferenceType(xPopType)) - { - /* - * On the stack now: - * $esp + 0 Params - * $esp + xThisOffset This - */ - // we need to see if $this is a boxed object, and if so, we need to unbox it - XS.Set(EAX, ESP, sourceDisplacement: xThisOffset + 4); - XS.Compare(EAX, (int)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationIsIndirect: true, destinationDisplacement: 4, size: RegisterSize.Int32); - - /* - * On the stack now: - * $esp Params - * $esp + xThisOffset This - * - * ECX contains the method to call - * EAX contains the type pointer (not the handle!!) - */ - XS.Jump(CPU.ConditionalTestEnum.NotEqual, xCurrentMethodLabel + ".NotBoxedThis"); - - // we need to determine if we actually want to unbox the object, we do this here so the code isnt run too often - if (aTargetMethod.DeclaringType.IsInterface) - { - // always unbox in this case - } - else - { - XS.Push(EAX); // we will need this eax again - XS.Push(ECX); // the call will trash ecx - XS.Set(EAX, ESP, sourceDisplacement: xThisOffset + 12); - XS.Push(EAX, isIndirect: true); - - XS.Push(aTargetMethodUID); - - XS.Call(LabelName.Get(VTablesImplRefs.GetDeclaringTypeOfMethodForTypeRef)); - - XS.Pop(EBX); - XS.Pop(ECX); // recover after the call - XS.Pop(EAX); - - XS.Compare(EBX, VTablesImplRefs.GetTypeId(typeof(object))); - XS.Jump(CPU.ConditionalTestEnum.Equal, xCurrentMethodLabel + ".NotBoxedThis"); - XS.Compare(EBX, VTablesImplRefs.GetTypeId(typeof(ValueType))); - XS.Jump(CPU.ConditionalTestEnum.Equal, xCurrentMethodLabel + ".NotBoxedThis"); - XS.Compare(EBX, VTablesImplRefs.GetTypeId(typeof(Enum))); - XS.Jump(CPU.ConditionalTestEnum.Equal, xCurrentMethodLabel + ".NotBoxedThis"); - } - - - /* - * On the stack now: - * $esp Params - * $esp + xThisOffset This - * - * ECX contains the method to call - * EAX contains the type pointer (not the handle!!) - */ - XS.Add(EAX, ObjectUtils.FieldDataOffset); - XS.Set(ESP, EAX, destinationDisplacement: xThisOffset + 4); - - var xHasParams = xThisOffset != 0; - var xNeedsExtraStackSize = xReturnSize >= xThisOffset + 8; - - if (xHasParams || !xNeedsExtraStackSize) - { - XS.Add(ESP, (uint)(xThisOffset + 4)); - } - - for (int i = 0; i < xThisOffset / 4; i++) - { - XS.Push(ESP, displacement: -8); - } - - if (xHasParams && xNeedsExtraStackSize) - { - XS.Sub(ESP, 4); - } - - /* - * On the stack now: - * $esp Params - * $esp + xThisOffset Pointer to address inside box - * - * ECX contains the method to call - */ - XS.Label(xCurrentMethodLabel + ".NotBoxedThis"); - } - - - if (xExtraStackSize > 0) - { - XS.Sub(ESP, xExtraStackSize); - } - - XS.Call(ECX); - XS.Label(afterCall); - } - EmitExceptionLogic(aAssembler, aMethod, aOp, true, - delegate - { - var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value; - - uint xPopSize = 0; - foreach (var type in aOp.StackPopTypes) - { - xPopSize += Align(SizeOfType(type), 4); - } - - var xResultSize = xReturnSize; - if (xResultSize % 4 != 0) - { - xResultSize += 4 - xResultSize % 4; - } - - EmitExceptionCleanupAfterCall(aAssembler, xResultSize, xStackOffsetBefore, xPopSize); - }); - XS.Label(xCurrentMethodLabel + ".NoExceptionAfterCall"); - } - } -} +using System; +using System.Linq; +using System.Reflection; + +using Cosmos.IL2CPU.ILOpCodes; + +using IL2CPU.API; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; +using CPU = XSharp.Assembler.x86; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Callvirt)] + public class Callvirt : ILOp + { + public Callvirt(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpMethod = aOpCode as OpMethod; + DoExecute(Assembler, aMethod, xOpMethod.Value, xOpMethod.ValueUID, aOpCode, DebugEnabled); + } + + public static void DoExecute(Assembler aAssembler, Il2cpuMethodInfo aMethod, MethodBase aTargetMethod, uint aTargetMethodUID, ILOpCode aOp, bool aDebugEnabled) + { + string xCurrentMethodLabel = GetLabel(aMethod, aOp.Position); + Type xPopType = aOp.StackPopTypes.Last(); + var isInterface = aTargetMethod.DeclaringType.IsInterface; + + string xNormalAddress = ""; + if (aTargetMethod.IsStatic || !aTargetMethod.IsVirtual || aTargetMethod.IsFinal) + { + xNormalAddress = LabelName.Get(aTargetMethod); + } + + uint xReturnSize = 0; + var xMethodInfo = aTargetMethod as MethodInfo; + if (xMethodInfo != null) + { + xReturnSize = Align(SizeOfType(xMethodInfo.ReturnType), 4); + } + + var xExtraStackSize = Call.GetStackSizeToReservate(aTargetMethod, xPopType); + int xThisOffset = 0; + var xParameters = aTargetMethod.GetParameters(); + foreach (var xItem in xParameters) + { + xThisOffset += (int)Align(SizeOfType(xItem.ParameterType), 4); + } + + // This is finding offset to self? It looks like we dont need offsets of other + // arguments, but only self. If so can calculate without calculating all fields + // Might have to go to old data structure for the offset... + // Can we add this method info somehow to the data passed in? + // mThisOffset = mTargetMethodInfo.Arguments[0].Offset; + XS.Comment($"Calling = {aTargetMethod.DeclaringType.FullName}.{aTargetMethod.Name}"); + XS.Comment("ThisOffset = " + xThisOffset); + + if (IsReferenceType(xPopType)) + { + DoNullReferenceCheck(aAssembler, aDebugEnabled, xThisOffset + 4); + } + else + { + DoNullReferenceCheck(aAssembler, aDebugEnabled, xThisOffset); + } + + if (!String.IsNullOrEmpty(xNormalAddress)) + { + if (xExtraStackSize > 0) + { + XS.Sub(RSP, xExtraStackSize); + } + + XS.Call(xNormalAddress); + } + else + { + var afterCall = xCurrentMethodLabel + ".AfterCall"; + + /* + * On the stack now: + * $esp Params + * $esp + xThisOffset This + */ + if (xPopType.IsPointer || xPopType.IsByRef) + { + xPopType = xPopType.GetElementType(); + XS.Push(GetTypeIDLabel(xPopType), isIndirect: true); + } + else + { + XS.Set(RAX, RSP, sourceDisplacement: xThisOffset + 4); + XS.Set(RBX, RAX, sourceDisplacement: 4, sourceIsIndirect: true); // type of object + XS.Push(RAX, isIndirect: true); + } + + // To handle generic interfaces on arrays, we need to check if the callvirt is for such an interface, in which case if the object + // the method is being called on is an array, we dont push the type array but rather an typed array (System.Array vs T[]) + + if (aTargetMethod.DeclaringType.IsGenericType + && new string[] { "IList", "ICollection", "IEnumerable", "IReadOnlyList", "IReadOnlyCollection" } + .Any(i => aTargetMethod.DeclaringType.Name.Contains(i))) + { + isInterface = true; + var notArrayLabel = xCurrentMethodLabel + ".NotArrayType"; + var endOfCheckLabel = xCurrentMethodLabel + ".AfterGenericArrayInterfaceCheck"; + XS.Pop(RAX); // EAX now contains type of object + // Now check if type derives from array + XS.Compare(RBX, (uint)ObjectUtils.InstanceTypeEnum.Array); + XS.Jump(CPU.ConditionalTestEnum.NotEqual, notArrayLabel); + XS.Comment($"Set type to be {aTargetMethod.DeclaringType.GenericTypeArguments[0].MakeArrayType().Name}"); + XS.Push(GetTypeIDLabel(aTargetMethod.DeclaringType.GenericTypeArguments[0].MakeArrayType()), isIndirect: true); + XS.Jump(endOfCheckLabel); + XS.Label(notArrayLabel); // we already pushed that value when it does not need to be overwritten + XS.Push(RAX); + XS.Label(endOfCheckLabel); + } + + XS.Push(aTargetMethodUID); + + if (isInterface) + { + XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForInterfaceTypeRef)); + } + else + { + XS.Call(LabelName.Get(VTablesImplRefs.GetMethodAddressForTypeRef)); + } + + if (xExtraStackSize > 0) + { + xThisOffset -= (int)xExtraStackSize; + } + + /* + * On the stack now: + * $esp Params + * $esp + xThisOffset This + */ + XS.Pop(RCX); + + XS.Label(xCurrentMethodLabel + ".AfterAddressCheck"); + + if (IsReferenceType(xPopType)) + { + /* + * On the stack now: + * $esp + 0 Params + * $esp + xThisOffset This + */ + // we need to see if $this is a boxed object, and if so, we need to unbox it + XS.Set(RAX, RSP, sourceDisplacement: xThisOffset + 4); + XS.Compare(RAX, (int)ObjectUtils.InstanceTypeEnum.BoxedValueType, destinationIsIndirect: true, destinationDisplacement: 4, size: RegisterSize.Long64); + + /* + * On the stack now: + * $esp Params + * $esp + xThisOffset This + * + * ECX contains the method to call + * EAX contains the type pointer (not the handle!!) + */ + XS.Jump(CPU.ConditionalTestEnum.NotEqual, xCurrentMethodLabel + ".NotBoxedThis"); + + // we need to determine if we actually want to unbox the object, we do this here so the code isnt run too often + if (aTargetMethod.DeclaringType.IsInterface) + { + // always unbox in this case + } + else + { + XS.Push(RAX); // we will need this eax again + XS.Push(RCX); // the call will trash ecx + XS.Set(RAX, RSP, sourceDisplacement: xThisOffset + 12); + XS.Push(RAX, isIndirect: true); + + XS.Push(aTargetMethodUID); + + XS.Call(LabelName.Get(VTablesImplRefs.GetDeclaringTypeOfMethodForTypeRef)); + + XS.Pop(RBX); + XS.Pop(RCX); // recover after the call + XS.Pop(RAX); + + XS.Compare(RBX, VTablesImplRefs.GetTypeId(typeof(object))); + XS.Jump(CPU.ConditionalTestEnum.Equal, xCurrentMethodLabel + ".NotBoxedThis"); + XS.Compare(RBX, VTablesImplRefs.GetTypeId(typeof(ValueType))); + XS.Jump(CPU.ConditionalTestEnum.Equal, xCurrentMethodLabel + ".NotBoxedThis"); + XS.Compare(RBX, VTablesImplRefs.GetTypeId(typeof(Enum))); + XS.Jump(CPU.ConditionalTestEnum.Equal, xCurrentMethodLabel + ".NotBoxedThis"); + } + + + /* + * On the stack now: + * $esp Params + * $esp + xThisOffset This + * + * ECX contains the method to call + * EAX contains the type pointer (not the handle!!) + */ + XS.Add(RAX, ObjectUtils.FieldDataOffset); + XS.Set(RSP, RAX, destinationDisplacement: xThisOffset + 4); + + var xHasParams = xThisOffset != 0; + var xNeedsExtraStackSize = xReturnSize >= xThisOffset + 8; + + if (xHasParams || !xNeedsExtraStackSize) + { + XS.Add(RSP, (uint)(xThisOffset + 4)); + } + + for (int i = 0; i < xThisOffset / 4; i++) + { + XS.Push(RSP, displacement: -8); + } + + if (xHasParams && xNeedsExtraStackSize) + { + XS.Sub(RSP, 4); + } + + /* + * On the stack now: + * $esp Params + * $esp + xThisOffset Pointer to address inside box + * + * ECX contains the method to call + */ + XS.Label(xCurrentMethodLabel + ".NotBoxedThis"); + } + + + if (xExtraStackSize > 0) + { + XS.Sub(RSP, xExtraStackSize); + } + + XS.Call(RCX); + XS.Label(afterCall); + } + EmitExceptionLogic(aAssembler, aMethod, aOp, true, + delegate + { + var xStackOffsetBefore = aOp.StackOffsetBeforeExecution.Value; + + uint xPopSize = 0; + foreach (var type in aOp.StackPopTypes) + { + xPopSize += Align(SizeOfType(type), 4); + } + + var xResultSize = xReturnSize; + if (xResultSize % 4 != 0) + { + xResultSize += 4 - xResultSize % 4; + } + + EmitExceptionCleanupAfterCall(aAssembler, xResultSize, xStackOffsetBefore, xPopSize); + }); + XS.Label(xCurrentMethodLabel + ".NoExceptionAfterCall"); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Castclass.cs b/source/Cosmos.IL2CPU/IL/Castclass.cs index 4de9ac784..259962f50 100644 --- a/source/Cosmos.IL2CPU/IL/Castclass.cs +++ b/source/Cosmos.IL2CPU/IL/Castclass.cs @@ -1,56 +1,56 @@ -using System; -using System.Reflection; - -using IL2CPU.API; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Castclass)] - public class Castclass : ILOp - { - public Castclass(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = (OpType)aOpCode; - var xTypeID = GetTypeIDLabel(xType.Value); - - var xCurrentMethodLabel = GetLabel(aMethod, aOpCode); - var xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; - var xInvalidCastLabel = xCurrentMethodLabel + "_InvalidCast"; - var xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); - - XS.Set(EAX, ESP, sourceDisplacement: 4); - - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Zero, xNextPositionLabel); - XS.Push(EAX, isIndirect: true); - XS.Push(xTypeID, isIndirect: true); - XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); - - MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef; - - Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); - - XS.Label(xAfterIsInstanceCallLabel); - - XS.Pop(EAX); - - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Equal, xInvalidCastLabel); - - XS.Jump(xNextPositionLabel); - - XS.Label(xInvalidCastLabel); - XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef)); - } - } -} +using System; +using System.Reflection; + +using IL2CPU.API; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Castclass)] + public class Castclass : ILOp + { + public Castclass(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = (OpType)aOpCode; + var xTypeID = GetTypeIDLabel(xType.Value); + + var xCurrentMethodLabel = GetLabel(aMethod, aOpCode); + var xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; + var xInvalidCastLabel = xCurrentMethodLabel + "_InvalidCast"; + var xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); + + XS.Set(RAX, RSP, sourceDisplacement: 4); + + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Zero, xNextPositionLabel); + XS.Push(RAX, isIndirect: true); + XS.Push(xTypeID, isIndirect: true); + XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); + + MethodBase xMethodIsInstance = VTablesImplRefs.IsInstanceRef; + + Call.DoExecute(Assembler, aMethod, xMethodIsInstance, aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); + + XS.Label(xAfterIsInstanceCallLabel); + + XS.Pop(RAX); + + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Equal, xInvalidCastLabel); + + XS.Jump(xNextPositionLabel); + + XS.Label(xInvalidCastLabel); + XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef)); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ceq.cs b/source/Cosmos.IL2CPU/IL/Ceq.cs index ae58d79f3..4941cf003 100644 --- a/source/Cosmos.IL2CPU/IL/Ceq.cs +++ b/source/Cosmos.IL2CPU/IL/Ceq.cs @@ -1,123 +1,123 @@ -using System; -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ceq)] - public class Ceq : ILOp - { - public Ceq(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xStackItemSize = SizeOfType(xStackItem); - var xStackItemIsFloat = TypeIsFloat(xStackItem); - var xStackItem2 = aOpCode.StackPopTypes[1]; - var xStackItem2Size = SizeOfType(xStackItem2); - var xStackItem2IsFloat = TypeIsFloat(xStackItem2); - var xSize = Math.Max(xStackItemSize, xStackItem2Size); - - var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition); - - if (xSize > 8) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: StackSizes > 8 not supported"); - } - else if (xSize <= 4) - { - if (xStackItemIsFloat) // float - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.CompareSS(XMM1, XMM0, comparision: Equal); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Xor(EBX, EBX); - XS.Pop(ECX); - XS.Pop(EAX); - XS.Compare(EAX, ECX); - XS.SetByteOnCondition(ConditionalTestEnum.Equal, BL); - XS.Push(EBX); - } - } - else if (xSize > 4) - { - if (xStackItemIsFloat) - { - // Please note that SSE supports double operations only from version 2 - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - // Increment ESP to get the value of the next double - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.CompareSD(XMM1, XMM0, comparision: Equal); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! - XS.Add(ESP, 4); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - if (IsReferenceType(xStackItem) && IsReferenceType(xStackItem2)) - { - XS.Comment(xStackItem.Name); - XS.Add(ESP, 4); - XS.Pop(EAX); - - XS.Comment(xStackItem2.Name); - XS.Add(ESP, 4); - XS.Pop(EBX); - - XS.Compare(EAX, EBX); - XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False"); - - // equal - XS.Push(1); - XS.Jump(xNextLabel); - XS.Label(Label.LastFullLabel + ".False"); - //not equal - XS.Push(0); - XS.Jump(xNextLabel); - } - else - { - XS.Pop(EAX); - XS.Compare(EAX, ESP, sourceDisplacement: 4); - XS.Pop(EAX); - XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False"); - XS.Xor(EAX, ESP, sourceDisplacement: 4); - XS.Jump(ConditionalTestEnum.NotZero, Label.LastFullLabel + ".False"); - - //they are equal - XS.Add(ESP, 8); - XS.Push(1); - XS.Jump(xNextLabel); - XS.Label(Label.LastFullLabel + ".False"); - //not equal - XS.Add(ESP, 8); - XS.Push(0); - XS.Jump(xNextLabel); - - } - } - } - else - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: Case not handled!"); - } - } - } -} +using System; +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ceq)] + public class Ceq : ILOp + { + public Ceq(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xStackItemSize = SizeOfType(xStackItem); + var xStackItemIsFloat = TypeIsFloat(xStackItem); + var xStackItem2 = aOpCode.StackPopTypes[1]; + var xStackItem2Size = SizeOfType(xStackItem2); + var xStackItem2IsFloat = TypeIsFloat(xStackItem2); + var xSize = Math.Max(xStackItemSize, xStackItem2Size); + + var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition); + + if (xSize > 8) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: StackSizes > 8 not supported"); + } + else if (xSize <= 4) + { + if (xStackItemIsFloat) // float + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.CompareSS(XMM1, XMM0, comparision: Equal); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Xor(RBX, RBX); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Compare(RAX, RCX); + XS.SetByteOnCondition(ConditionalTestEnum.Equal, BL); + XS.Push(RBX); + } + } + else if (xSize > 4) + { + if (xStackItemIsFloat) + { + // Please note that SSE supports double operations only from version 2 + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + // Increment ESP to get the value of the next double + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.CompareSD(XMM1, XMM0, comparision: Equal); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! + XS.Add(RSP, 4); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + if (IsReferenceType(xStackItem) && IsReferenceType(xStackItem2)) + { + XS.Comment(xStackItem.Name); + XS.Add(RSP, 4); + XS.Pop(RAX); + + XS.Comment(xStackItem2.Name); + XS.Add(RSP, 4); + XS.Pop(RBX); + + XS.Compare(RAX, RBX); + XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False"); + + // equal + XS.Push(1); + XS.Jump(xNextLabel); + XS.Label(Label.LastFullLabel + ".False"); + //not equal + XS.Push(0); + XS.Jump(xNextLabel); + } + else + { + XS.Pop(RAX); + XS.Compare(RAX, RSP, sourceDisplacement: 4); + XS.Pop(RAX); + XS.Jump(ConditionalTestEnum.NotEqual, Label.LastFullLabel + ".False"); + XS.Xor(RAX, RSP, sourceDisplacement: 4); + XS.Jump(ConditionalTestEnum.NotZero, Label.LastFullLabel + ".False"); + + //they are equal + XS.Add(RSP, 8); + XS.Push(1); + XS.Jump(xNextLabel); + XS.Label(Label.LastFullLabel + ".False"); + //not equal + XS.Add(RSP, 8); + XS.Push(0); + XS.Jump(xNextLabel); + + } + } + } + else + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Ceq.cs->Error: Case not handled!"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Cgt.cs b/source/Cosmos.IL2CPU/IL/Cgt.cs index 5dab38ce2..900876aa1 100644 --- a/source/Cosmos.IL2CPU/IL/Cgt.cs +++ b/source/Cosmos.IL2CPU/IL/Cgt.cs @@ -1,116 +1,116 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; -using CPU = XSharp.Assembler.x86; -using XSharp.Assembler.x86; -using XSharp.Assembler; -using XSharp.Assembler.x86.SSE; -using XSharp.Assembler.x86.x87; - -using XSharp; -using static XSharp.XSRegisters; -using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Cgt)] - public class Cgt : ILOp - { - public Cgt(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xStackItemSize = SizeOfType(xStackItem); - var xStackItemIsFloat = TypeIsFloat(xStackItem); - if (xStackItemSize > 8) - { - //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Cgt.cs->Error: StackSizes > 8 not supported"); - //return; - } - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LabelTrue = BaseLabel + "True"; - string LabelFalse = BaseLabel + "False"; - var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition); - if (xStackItemSize > 4) - { - // Using SSE registers (that do NOT branch!) This is needed only for long now -#if false - XS.Set(XSRegisters.ESI, 1); - // esi = 1 - XS.Xor(XSRegisters.EDI, XSRegisters.EDI); - // edi = 0 -#endif - if (xStackItemIsFloat) - { - // Please note that SSE supports double operations only from version 2 - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - // Increment ESP to get the value of the next double - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.CompareSD(XMM1, XMM0, comparision: NotLessThanOrEqualTo); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! - XS.Add(ESP, 4); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Set(ESI, 1); - // esi = 1 - XS.Xor(EDI, EDI); - // edi = 0 - - XS.Pop(EAX); - XS.Pop(EDX); - //value2: EDX:EAX - XS.Pop(EBX); - XS.Pop(ECX); - //value1: ECX:EBX - - XS.Compare(ECX, EDX); - XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue); - XS.Jump(ConditionalTestEnum.LessThan, LabelFalse); - XS.Compare(EBX, EAX); - XS.Label(LabelTrue); - new ConditionalMove { Condition = ConditionalTestEnum.Above, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; - XS.Label(LabelFalse); - XS.Push(EDI); - } - /* - XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue); - XS.Label(LabelFalse); - XS.Push(0); - XS.Jump(xNextLabel); - XS.Label(LabelTrue ); - XS.Push(1);*/ - } - else - { - if (xStackItemIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(XSRegisters.ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.CompareSS(XMM1, XMM0, comparision: NotLessThanOrEqualTo); - XS.MoveD(EBX, XMM1); - XS.And(XSRegisters.EBX, 1); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Xor(EBX, EBX); - XS.Pop(ECX); - XS.Pop(EAX); - XS.Compare(EAX, ECX); - XS.SetByteOnCondition(ConditionalTestEnum.GreaterThan, BL); - XS.Push(EBX); - } - } - } - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; +using CPU = XSharp.Assembler.x86; +using XSharp.Assembler.x86; +using XSharp.Assembler; +using XSharp.Assembler.x86.SSE; +using XSharp.Assembler.x86.x87; + +using XSharp; +using static XSharp.XSRegisters; +using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Cgt)] + public class Cgt : ILOp + { + public Cgt(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xStackItemSize = SizeOfType(xStackItem); + var xStackItemIsFloat = TypeIsFloat(xStackItem); + if (xStackItemSize > 8) + { + //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Cgt.cs->Error: StackSizes > 8 not supported"); + //return; + } + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LabelTrue = BaseLabel + "True"; + string LabelFalse = BaseLabel + "False"; + var xNextLabel = GetLabel(aMethod, aOpCode.NextPosition); + if (xStackItemSize > 4) + { + // Using SSE registers (that do NOT branch!) This is needed only for long now +#if false + XS.Set(XSRegisters.ESI, 1); + // esi = 1 + XS.Xor(XSRegisters.EDI, XSRegisters.EDI); + // edi = 0 +#endif + if (xStackItemIsFloat) + { + // Please note that SSE supports double operations only from version 2 + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + // Increment ESP to get the value of the next double + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.CompareSD(XMM1, XMM0, comparision: NotLessThanOrEqualTo); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! + XS.Add(RSP, 4); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Set(RSI, 1); + // esi = 1 + XS.Xor(RDI, RDI); + // edi = 0 + + XS.Pop(RAX); + XS.Pop(RDX); + //value2: EDX:EAX + XS.Pop(RBX); + XS.Pop(RCX); + //value1: ECX:EBX + + XS.Compare(RCX, RDX); + XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue); + XS.Jump(ConditionalTestEnum.LessThan, LabelFalse); + XS.Compare(RBX, RAX); + XS.Label(LabelTrue); + new ConditionalMove { Condition = ConditionalTestEnum.Above, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; + XS.Label(LabelFalse); + XS.Push(RDI); + } + /* + XS.Jump(ConditionalTestEnum.GreaterThan, LabelTrue); + XS.Label(LabelFalse); + XS.Push(0); + XS.Jump(xNextLabel); + XS.Label(LabelTrue ); + XS.Push(1);*/ + } + else + { + if (xStackItemIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(XSRegisters.RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.CompareSS(XMM1, XMM0, comparision: NotLessThanOrEqualTo); + XS.MoveD(RBX, XMM1); + XS.And(XSRegisters.RBX, 1); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Xor(RBX, RBX); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Compare(RAX, RCX); + XS.SetByteOnCondition(ConditionalTestEnum.GreaterThan, BL); + XS.Push(RBX); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Cgt_Un.cs b/source/Cosmos.IL2CPU/IL/Cgt_Un.cs index 3f6c93c8c..81e210cb0 100644 --- a/source/Cosmos.IL2CPU/IL/Cgt_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Cgt_Un.cs @@ -1,199 +1,199 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; -using CPU = XSharp.Assembler.x86; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using XSharp.Assembler.x86.SSE; -using XSharp.Assembler.x86.x87; - -using XSharp; -using static XSharp.XSRegisters; -using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Cgt_Un )] - public class Cgt_Un : ILOp - { - public Cgt_Un( XSharp.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xStackItemSize = SizeOfType(xStackItem); - var xStackItemIsFloat = TypeIsFloat(xStackItem); - if( xStackItemSize > 8 ) - { - //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt_Un: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Cgt_Un.cs->Error: StackSizes > 8 not supported"); - } - string BaseLabel = GetLabel( aMethod, aOpCode ) + "."; - string LabelTrue = BaseLabel + "True"; - string LabelFalse = BaseLabel + "False"; - if( xStackItemSize > 4 ) - { - // Using SSE registers (that do NOT branch!) This is needed only for long now -#if false - XS.Set(XSRegisters.ESI, 1); - // esi = 1 - XS.Xor(XSRegisters.EDI, XSRegisters.EDI); - // edi = 0 -#endif - if (xStackItemIsFloat) - { - // Please note that SSE supports double operations only from version 2 - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - // Increment ESP to get the value of the next double - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.CompareSD(XMM1, XMM0, comparision: NotLessThanOrEqualTo); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! - XS.Add(ESP, 4); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Set(XSRegisters.ESI, 1); - // esi = 1 - XS.Xor(XSRegisters.EDI, XSRegisters.EDI); - // edi = 0 - XS.Pop(XSRegisters.EAX); - XS.Pop(XSRegisters.EDX); - //value2: EDX:EAX - XS.Pop(XSRegisters.EBX); - XS.Pop(XSRegisters.ECX); - //value1: ECX:EBX - - XS.Compare(XSRegisters.ECX, XSRegisters.EDX); - XS.Jump(ConditionalTestEnum.Above, LabelTrue); - XS.Jump(ConditionalTestEnum.Below, LabelFalse); - XS.Compare(XSRegisters.EBX, XSRegisters.EAX); - XS.Label(LabelTrue); - new ConditionalMove { Condition = ConditionalTestEnum.Above, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; - XS.Label(LabelFalse); - XS.Push(XSRegisters.EDI); - } - /* - XS.Jump(ConditionalTestEnum.Above, LabelTrue); - XS.Label(LabelFalse); - XS.Push(0); - new CPUx86.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; - XS.Label(LabelTrue ); - XS.Push(1); - */ - } - else - { - if (xStackItemIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.CompareSS(XMM1, XMM0, comparision: NotLessThanOrEqualTo); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Xor(EBX, EBX); - XS.Pop(ECX); - XS.Pop(EAX); - XS.Compare(EAX, ECX); - XS.SetByteOnCondition(ConditionalTestEnum.Above, BL); - XS.Push(EBX); - } - } - } - - // using System; - // - // using CPUx86 = XSharp.Assembler.x86; - // using CPU = XSharp.Assembler.x86; - // using Cosmos.IL2CPU.X86; - // using Cosmos.IL2CPU.X86; - // - // namespace Cosmos.IL2CPU.IL.X86 { - // [XSharp.Assembler.OpCode(OpCodeEnum.Cgt_Un)] - // public class Cgt_Un: Op { - // private readonly string NextInstructionLabel; - // private readonly string CurInstructionLabel; - // private uint mCurrentOffset; - // private MethodInformation mMethodInfo; - // public Cgt_Un(ILReader aReader, MethodInformation aMethodInfo) - // : base(aReader, aMethodInfo) - // { - // NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); - // CurInstructionLabel = GetInstructionLabel(aReader); - // mMethodInfo = aMethodInfo; - // mCurrentOffset = aReader.Position; - // } - // - // public override void DoAssemble() - // { - // var xStackItem = Assembler.Stack.Pop(); - // if (xStackItem.IsFloat) - // { - // EmitNotImplementedException(Assembler, GetServiceProvider(), "Cgt_Un: Floats not yet supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel); - // return; - // } - // if (xStackItem.Size > 8) - // { - // EmitNotImplementedException(Assembler, GetServiceProvider(), "Cgt_Un: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel); - // return; - // } - // Assembler.Stack.Push(new StackContent(4, typeof(bool))); - // string BaseLabel = CurInstructionLabel + "."; - // string LabelTrue = BaseLabel + "True"; - // string LabelFalse = BaseLabel + "False"; - // if (xStackItem.Size > 4) - // { - // XS.Xor(XSRegisters.ESI, XSRegisters.CPUx86.Registers.ESI); - // XS.Add(XSRegisters.ESI, 1); - // XS.Xor(XSRegisters.EDI, XSRegisters.CPUx86.Registers.EDI); - // //esi = 1 - // XS.Pop(XSRegisters.EAX); - // XS.Pop(XSRegisters.EDX); - // //value2: EDX:EAX - // XS.Pop(XSRegisters.EBX); - // XS.Pop(XSRegisters.ECX); - // //value1: ECX:EBX - // XS.Sub(XSRegisters.EBX, XSRegisters.CPUx86.Registers.EAX); - // XS.SubWithCarry(XSRegisters.ECX, XSRegisters.CPUx86.Registers.EDX); - // //result = value1 - value2 - // //new CPUx86.ConditionalMove(Condition.Above, "edi", "esi"); - // //XS.Push(XSRegisters.EDI); - // - // XS.Jump(ConditionalTestEnum.Above, LabelTrue); - // XS.Push(0); - // XS.Jump(NextInstructionLabel); - // - // XS.Label(LabelTrue); - // XS.Push(1); - // - // } else - // { - // XS.Pop(XSRegisters.EAX); - // XS.Compare(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true); - // XS.Jump(ConditionalTestEnum.Below, LabelTrue); - // XS.Jump(LabelFalse); - // XS.Label(LabelTrue); - // XS.Add(XSRegisters.ESP, 4); - // XS.Push(1); - // XS.Jump(NextInstructionLabel); - // XS.Label(LabelFalse); - // XS.Add(XSRegisters.ESP, 4); - // XS.Push(0); - // XS.Jump(NextInstructionLabel); - // } - // } - // } - // } - - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; +using CPU = XSharp.Assembler.x86; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using XSharp.Assembler.x86.SSE; +using XSharp.Assembler.x86.x87; + +using XSharp; +using static XSharp.XSRegisters; +using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Cgt_Un )] + public class Cgt_Un : ILOp + { + public Cgt_Un( XSharp.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xStackItemSize = SizeOfType(xStackItem); + var xStackItemIsFloat = TypeIsFloat(xStackItem); + if( xStackItemSize > 8 ) + { + //EmitNotImplementedException( Assembler, GetServiceProvider(), "Cgt_Un: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Cgt_Un.cs->Error: StackSizes > 8 not supported"); + } + string BaseLabel = GetLabel( aMethod, aOpCode ) + "."; + string LabelTrue = BaseLabel + "True"; + string LabelFalse = BaseLabel + "False"; + if( xStackItemSize > 4 ) + { + // Using SSE registers (that do NOT branch!) This is needed only for long now +#if false + XS.Set(XSRegisters.ESI, 1); + // esi = 1 + XS.Xor(XSRegisters.EDI, XSRegisters.EDI); + // edi = 0 +#endif + if (xStackItemIsFloat) + { + // Please note that SSE supports double operations only from version 2 + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + // Increment ESP to get the value of the next double + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.CompareSD(XMM1, XMM0, comparision: NotLessThanOrEqualTo); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! + XS.Add(RSP, 4); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Set(XSRegisters.RSI, 1); + // esi = 1 + XS.Xor(XSRegisters.RDI, XSRegisters.RDI); + // edi = 0 + XS.Pop(XSRegisters.RAX); + XS.Pop(XSRegisters.RDX); + //value2: EDX:EAX + XS.Pop(XSRegisters.RBX); + XS.Pop(XSRegisters.RCX); + //value1: ECX:EBX + + XS.Compare(XSRegisters.RCX, XSRegisters.RDX); + XS.Jump(ConditionalTestEnum.Above, LabelTrue); + XS.Jump(ConditionalTestEnum.Below, LabelFalse); + XS.Compare(XSRegisters.RBX, XSRegisters.RAX); + XS.Label(LabelTrue); + new ConditionalMove { Condition = ConditionalTestEnum.Above, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; + XS.Label(LabelFalse); + XS.Push(XSRegisters.RDI); + } + /* + XS.Jump(ConditionalTestEnum.Above, LabelTrue); + XS.Label(LabelFalse); + XS.Push(0); + new CPUx86.Jump { DestinationLabel = GetLabel(aMethod, aOpCode.NextPosition) }; + XS.Label(LabelTrue ); + XS.Push(1); + */ + } + else + { + if (xStackItemIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.CompareSS(XMM1, XMM0, comparision: NotLessThanOrEqualTo); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Xor(RBX, RBX); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Compare(RAX, RCX); + XS.SetByteOnCondition(ConditionalTestEnum.Above, BL); + XS.Push(RBX); + } + } + } + + // using System; + // + // using CPUx86 = XSharp.Assembler.x86; + // using CPU = XSharp.Assembler.x86; + // using Cosmos.IL2CPU.X86; + // using Cosmos.IL2CPU.X86; + // + // namespace Cosmos.IL2CPU.IL.X86 { + // [XSharp.Assembler.OpCode(OpCodeEnum.Cgt_Un)] + // public class Cgt_Un: Op { + // private readonly string NextInstructionLabel; + // private readonly string CurInstructionLabel; + // private uint mCurrentOffset; + // private MethodInformation mMethodInfo; + // public Cgt_Un(ILReader aReader, MethodInformation aMethodInfo) + // : base(aReader, aMethodInfo) + // { + // NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); + // CurInstructionLabel = GetInstructionLabel(aReader); + // mMethodInfo = aMethodInfo; + // mCurrentOffset = aReader.Position; + // } + // + // public override void DoAssemble() + // { + // var xStackItem = Assembler.Stack.Pop(); + // if (xStackItem.IsFloat) + // { + // EmitNotImplementedException(Assembler, GetServiceProvider(), "Cgt_Un: Floats not yet supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel); + // return; + // } + // if (xStackItem.Size > 8) + // { + // EmitNotImplementedException(Assembler, GetServiceProvider(), "Cgt_Un: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel); + // return; + // } + // Assembler.Stack.Push(new StackContent(4, typeof(bool))); + // string BaseLabel = CurInstructionLabel + "."; + // string LabelTrue = BaseLabel + "True"; + // string LabelFalse = BaseLabel + "False"; + // if (xStackItem.Size > 4) + // { + // XS.Xor(XSRegisters.ESI, XSRegisters.CPUx86.Registers.ESI); + // XS.Add(XSRegisters.ESI, 1); + // XS.Xor(XSRegisters.EDI, XSRegisters.CPUx86.Registers.EDI); + // //esi = 1 + // XS.Pop(XSRegisters.EAX); + // XS.Pop(XSRegisters.EDX); + // //value2: EDX:EAX + // XS.Pop(XSRegisters.EBX); + // XS.Pop(XSRegisters.ECX); + // //value1: ECX:EBX + // XS.Sub(XSRegisters.EBX, XSRegisters.CPUx86.Registers.EAX); + // XS.SubWithCarry(XSRegisters.ECX, XSRegisters.CPUx86.Registers.EDX); + // //result = value1 - value2 + // //new CPUx86.ConditionalMove(Condition.Above, "edi", "esi"); + // //XS.Push(XSRegisters.EDI); + // + // XS.Jump(ConditionalTestEnum.Above, LabelTrue); + // XS.Push(0); + // XS.Jump(NextInstructionLabel); + // + // XS.Label(LabelTrue); + // XS.Push(1); + // + // } else + // { + // XS.Pop(XSRegisters.EAX); + // XS.Compare(XSRegisters.EAX, XSRegisters.ESP, sourceIsIndirect: true); + // XS.Jump(ConditionalTestEnum.Below, LabelTrue); + // XS.Jump(LabelFalse); + // XS.Label(LabelTrue); + // XS.Add(XSRegisters.ESP, 4); + // XS.Push(1); + // XS.Jump(NextInstructionLabel); + // XS.Label(LabelFalse); + // XS.Add(XSRegisters.ESP, 4); + // XS.Push(0); + // XS.Jump(NextInstructionLabel); + // } + // } + // } + // } + + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ckfinite.cs b/source/Cosmos.IL2CPU/IL/Ckfinite.cs index 9d70dab5d..ca57d33ff 100644 --- a/source/Cosmos.IL2CPU/IL/Ckfinite.cs +++ b/source/Cosmos.IL2CPU/IL/Ckfinite.cs @@ -1,57 +1,57 @@ -using System; - -using IL2CPU.API; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ckfinite)] - public class Ckfinite : ILOp - { - public Ckfinite(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackType = aOpCode.StackPopTypes[0]; - - var xNoThrowLabel = GetLabel(aMethod, aOpCode) + ".NoThrow"; - - switch (SizeOfType(xStackType)) - { - case 4: - XS.Pop(EAX); - XS.And(EAX, 0x7FFFFFFF); - - XS.Compare(EAX, 0x7F800000); - XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel); - - XS.SSE2.ConvertSS2SD(XMM0, EAX); - XS.Sub(ESP, 8); - XS.SSE2.MoveSD(ESP, XMM0, true); - - break; - case 8: - XS.Set(EAX, ESP, sourceDisplacement: 4); - - XS.And(EAX, 0x7FFFFFFF); - XS.Compare(EAX, 0x7F800000); - XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel); - - break; - default: - throw new NotImplementedException(); - } - - XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowNotFiniteNumberExceptionRef)); - - XS.Label(xNoThrowLabel); - } - } -} +using System; + +using IL2CPU.API; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ckfinite)] + public class Ckfinite : ILOp + { + public Ckfinite(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackType = aOpCode.StackPopTypes[0]; + + var xNoThrowLabel = GetLabel(aMethod, aOpCode) + ".NoThrow"; + + switch (SizeOfType(xStackType)) + { + case 4: + XS.Pop(RAX); + XS.And(RAX, 0x7FFFFFFF); + + XS.Compare(RAX, 0x7F800000); + XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel); + + XS.SSE2.ConvertSS2SD(XMM0, RAX); + XS.Sub(RSP, 8); + XS.SSE2.MoveSD(RSP, XMM0, true); + + break; + case 8: + XS.Set(RAX, RSP, sourceDisplacement: 4); + + XS.And(RAX, 0x7FFFFFFF); + XS.Compare(RAX, 0x7F800000); + XS.Jump(ConditionalTestEnum.Below, xNoThrowLabel); + + break; + default: + throw new NotImplementedException(); + } + + XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowNotFiniteNumberExceptionRef)); + + XS.Label(xNoThrowLabel); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Clt.cs b/source/Cosmos.IL2CPU/IL/Clt.cs index e2e0d7ee2..72ab219eb 100644 --- a/source/Cosmos.IL2CPU/IL/Clt.cs +++ b/source/Cosmos.IL2CPU/IL/Clt.cs @@ -1,137 +1,137 @@ -using System; -using XSharp.Assembler; -using Cosmos.IL2CPU.ILOpCodes; -using CPUx86 = XSharp.Assembler.x86; -using CPU = XSharp.Assembler.x86; -using XSharp.Assembler.x86; -using XSharp.Assembler.x86.SSE; -using XSharp.Assembler.x86.x87; - -using XSharp; -using static XSharp.XSRegisters; -using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Compares two values. If the first value is less than the second, the integer value 1 (int32) is pushed onto the evaluation stack; - /// otherwise 0 (int32) is pushed onto the evaluation stack. - /// - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Clt )] - public class Clt : ILOp - { - public Clt( XSharp.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xStackItemSize = SizeOfType(xStackItem); - var xStackItemIsFloat = TypeIsFloat(xStackItem); - if( xStackItemSize > 8 ) - { - //EmitNotImplementedException( Assembler, GetServiceProvider(), "Clt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt.cs->Error: StackSizes > 8 not supported"); - //return; - } - if( xStackItemSize > 4 ) - { - // Using SSE registers (that do NOT branch!) This is needed only for long now -#if false - XS.Set(XSRegisters.ESI, 1); - // esi = 1 - XS.Xor(XSRegisters.EDI, XSRegisters.EDI); - // edi = 0 -#endif - if (xStackItemIsFloat) - { - // Please note that SSE supports double operations only from version 2 - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - // Increment ESP to get the value of the next double - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.CompareSD(XMM1, XMM0, comparision: LessThan); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! - XS.Add(ESP, 4); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Set(ESI, 1); - // esi = 1 - XS.Xor(EDI, EDI); - // edi = 0 - XS.Pop(EAX); - XS.Pop(EDX); - //value2: EDX:EAX - XS.Pop(EBX); - XS.Pop(ECX); - //value1: ECX:EBX - XS.Sub(EBX, EAX); - XS.SubWithCarry(ECX, EDX); - //result = value1 - value2 - - new ConditionalMove { Condition = ConditionalTestEnum.LessThan, DestinationReg = EDI, SourceReg = ESI }; - XS.Push(EDI); - } - } - else - { - if (xStackItemIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.CompareSS(XMM1, XMM0, comparision: LessThan); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Xor(EBX, EBX); - XS.Pop(ECX); - XS.Pop(EAX); - XS.Compare(EAX, ECX); - XS.SetByteOnCondition(ConditionalTestEnum.LessThan, BL); - XS.Push(EBX); - } - } - } - - - // using System; - // using System.IO; - // - // - // using CPUx86 = XSharp.Assembler.x86; - // using CPU = XSharp.Assembler.x86; - // using Cosmos.IL2CPU.X86; - // using Cosmos.IL2CPU.X86; - // - // namespace Cosmos.IL2CPU.IL.X86 { - // [XSharp.Assembler.OpCode(OpCodeEnum.Clt)] - // public class Clt: Op { - // private readonly string NextInstructionLabel; - // private readonly string CurInstructionLabel; - // private uint mCurrentOffset; - // private MethodInformation mMethodInfo; - // public Clt(ILReader aReader, MethodInformation aMethodInfo) - // : base(aReader, aMethodInfo) { - // NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); - // CurInstructionLabel = GetInstructionLabel(aReader); - // mMethodInfo = aMethodInfo; - // mCurrentOffset = aReader.Position; - // } - // public override void DoAssemble() { - - // } - // } - // } - - } -} +using System; +using XSharp.Assembler; +using Cosmos.IL2CPU.ILOpCodes; +using CPUx86 = XSharp.Assembler.x86; +using CPU = XSharp.Assembler.x86; +using XSharp.Assembler.x86; +using XSharp.Assembler.x86.SSE; +using XSharp.Assembler.x86.x87; + +using XSharp; +using static XSharp.XSRegisters; +using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Compares two values. If the first value is less than the second, the integer value 1 (int32) is pushed onto the evaluation stack; + /// otherwise 0 (int32) is pushed onto the evaluation stack. + /// + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Clt )] + public class Clt : ILOp + { + public Clt( XSharp.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xStackItemSize = SizeOfType(xStackItem); + var xStackItemIsFloat = TypeIsFloat(xStackItem); + if( xStackItemSize > 8 ) + { + //EmitNotImplementedException( Assembler, GetServiceProvider(), "Clt: StackSizes>8 not supported", CurInstructionLabel, mMethodInfo, mCurrentOffset, NextInstructionLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt.cs->Error: StackSizes > 8 not supported"); + //return; + } + if( xStackItemSize > 4 ) + { + // Using SSE registers (that do NOT branch!) This is needed only for long now +#if false + XS.Set(XSRegisters.ESI, 1); + // esi = 1 + XS.Xor(XSRegisters.EDI, XSRegisters.EDI); + // edi = 0 +#endif + if (xStackItemIsFloat) + { + // Please note that SSE supports double operations only from version 2 + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + // Increment ESP to get the value of the next double + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.CompareSD(XMM1, XMM0, comparision: LessThan); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! + XS.Add(RSP, 4); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Set(RSI, 1); + // esi = 1 + XS.Xor(RDI, RDI); + // edi = 0 + XS.Pop(RAX); + XS.Pop(RDX); + //value2: EDX:EAX + XS.Pop(RBX); + XS.Pop(RCX); + //value1: ECX:EBX + XS.Sub(RBX, RAX); + XS.SubWithCarry(RCX, RDX); + //result = value1 - value2 + + new ConditionalMove { Condition = ConditionalTestEnum.LessThan, DestinationReg = RDI, SourceReg = RSI }; + XS.Push(RDI); + } + } + else + { + if (xStackItemIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.CompareSS(XMM1, XMM0, comparision: LessThan); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Xor(RBX, RBX); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Compare(RAX, RCX); + XS.SetByteOnCondition(ConditionalTestEnum.LessThan, BL); + XS.Push(RBX); + } + } + } + + + // using System; + // using System.IO; + // + // + // using CPUx86 = XSharp.Assembler.x86; + // using CPU = XSharp.Assembler.x86; + // using Cosmos.IL2CPU.X86; + // using Cosmos.IL2CPU.X86; + // + // namespace Cosmos.IL2CPU.IL.X86 { + // [XSharp.Assembler.OpCode(OpCodeEnum.Clt)] + // public class Clt: Op { + // private readonly string NextInstructionLabel; + // private readonly string CurInstructionLabel; + // private uint mCurrentOffset; + // private MethodInformation mMethodInfo; + // public Clt(ILReader aReader, MethodInformation aMethodInfo) + // : base(aReader, aMethodInfo) { + // NextInstructionLabel = GetInstructionLabel(aReader.NextPosition); + // CurInstructionLabel = GetInstructionLabel(aReader); + // mMethodInfo = aMethodInfo; + // mCurrentOffset = aReader.Position; + // } + // public override void DoAssemble() { + + // } + // } + // } + + } +} diff --git a/source/Cosmos.IL2CPU/IL/Clt_Un.cs b/source/Cosmos.IL2CPU/IL/Clt_Un.cs index 7aa7e89cf..1a9e412d0 100644 --- a/source/Cosmos.IL2CPU/IL/Clt_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Clt_Un.cs @@ -1,99 +1,99 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; -using CPU = XSharp.Assembler.x86; -using XSharp.Assembler.x86; -using XSharp.Assembler; -using XSharp.Assembler.x86.SSE; -using XSharp.Assembler.x86.x87; - -using XSharp; -using static XSharp.XSRegisters; -using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Clt_Un )] - public class Clt_Un : ILOp - { - public Clt_Un( XSharp.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xStackItemSize = SizeOfType(xStackItem); - var xStackItemIsFloat = TypeIsFloat(xStackItem); - if( xStackItemSize > 8 ) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt_Un.cs->Error: StackSizes > 8 not supported"); - } - if (xStackItemSize > 4) - { - // Using SSE registers (that do NOT branch!) This is needed only for long now -#if false - XS.Set(XSRegisters.ESI, 1); - // esi = 1 - XS.Xor(XSRegisters.EDI, XSRegisters.EDI); - // edi = 0 -#endif - if (xStackItemIsFloat) - { - // Please note that SSE supports double operations only from version 2 - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - // Increment ESP to get the value of the next double - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.CompareSD(XMM1, XMM0, comparision: LessThan); - XS.MoveD(EBX, XMM1); - XS.And(EBX, 1); - // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! - XS.Add(ESP, 4); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Set(ESI, 1); - // esi = 1 - XS.Xor(EDI, EDI); - // edi = 0 - XS.Pop(EAX); - XS.Pop(EDX); - //value2: EDX:EAX - XS.Pop(EBX); - XS.Pop(ECX); - //value1: ECX:EBX - XS.Sub(EBX, EAX); - XS.SubWithCarry(ECX, EDX); - //result = value1 - value2 - new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; - XS.Push(XSRegisters.EDI); - } - } - else - { - if (xStackItemIsFloat) - { - XS.Comment("TEST TODO"); - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.CompareSS(XMM1, XMM0, comparision: LessThan); - XS.MoveD(EBX, XMM1); - XS.And(ESP, 1, destinationIsIndirect: true); - XS.Set(ESP, EBX, destinationIsIndirect: true); - } - else - { - XS.Xor(EBX, EBX); - XS.Pop(ECX); - XS.Pop(EAX); - XS.Compare(EAX, ECX); - XS.SetByteOnCondition(ConditionalTestEnum.Below, BL); - XS.Push(EBX); - } - } - } - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; +using CPU = XSharp.Assembler.x86; +using XSharp.Assembler.x86; +using XSharp.Assembler; +using XSharp.Assembler.x86.SSE; +using XSharp.Assembler.x86.x87; + +using XSharp; +using static XSharp.XSRegisters; +using static XSharp.Assembler.x86.SSE.ComparePseudoOpcodes; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Clt_Un )] + public class Clt_Un : ILOp + { + public Clt_Un( XSharp.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xStackItemSize = SizeOfType(xStackItem); + var xStackItemIsFloat = TypeIsFloat(xStackItem); + if( xStackItemSize > 8 ) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Clt_Un.cs->Error: StackSizes > 8 not supported"); + } + if (xStackItemSize > 4) + { + // Using SSE registers (that do NOT branch!) This is needed only for long now +#if false + XS.Set(XSRegisters.ESI, 1); + // esi = 1 + XS.Xor(XSRegisters.EDI, XSRegisters.EDI); + // edi = 0 +#endif + if (xStackItemIsFloat) + { + // Please note that SSE supports double operations only from version 2 + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + // Increment ESP to get the value of the next double + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.CompareSD(XMM1, XMM0, comparision: LessThan); + XS.MoveD(RBX, XMM1); + XS.And(RBX, 1); + // We need to move the stack pointer of 4 Byte to "eat" the second double that is yet in the stack or we get a corrupted stack! + XS.Add(RSP, 4); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Set(RSI, 1); + // esi = 1 + XS.Xor(RDI, RDI); + // edi = 0 + XS.Pop(RAX); + XS.Pop(RDX); + //value2: EDX:EAX + XS.Pop(RBX); + XS.Pop(RCX); + //value1: ECX:EBX + XS.Sub(RBX, RAX); + XS.SubWithCarry(RCX, RDX); + //result = value1 - value2 + new ConditionalMove { Condition = ConditionalTestEnum.Below, DestinationReg = RegistersEnum.EDI, SourceReg = RegistersEnum.ESI }; + XS.Push(XSRegisters.RDI); + } + } + else + { + if (xStackItemIsFloat) + { + XS.Comment("TEST TODO"); + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.CompareSS(XMM1, XMM0, comparision: LessThan); + XS.MoveD(RBX, XMM1); + XS.And(RSP, 1, destinationIsIndirect: true); + XS.Set(RSP, RBX, destinationIsIndirect: true); + } + else + { + XS.Xor(RBX, RBX); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Compare(RAX, RCX); + XS.SetByteOnCondition(ConditionalTestEnum.Below, BL); + XS.Push(RBX); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/ConvOverflowChecks.cs b/source/Cosmos.IL2CPU/IL/ConvOverflowChecks.cs index b9bd08b9f..89742a448 100644 --- a/source/Cosmos.IL2CPU/IL/ConvOverflowChecks.cs +++ b/source/Cosmos.IL2CPU/IL/ConvOverflowChecks.cs @@ -1,120 +1,120 @@ -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - class ConvOverflowChecks - { - public static void CheckOverflowForSmall(uint xResultSize, bool xSourceIsSigned, bool xResultIsSigned, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, string xSuccessLabel, string xOverflowLabel) - { - XS.Set(EAX, ESP, sourceIsIndirect: true); - // only look at bits which are part of result - // normally check that they are all either 0 or 1 - // if same size but casting between signed and unsigned, then first bit must be zero - byte bitCount = (byte)(xResultSize * 8 - 1); - XS.ShiftRight(EAX, bitCount); - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); - if (xSourceIsSigned) - { - if (xResultIsSigned) - { - XS.Not(EAX); // if negative then all must be 1s - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); - } - else - { - XS.Jump(xOverflowLabel); - } - } - else // source was unsigned - { - if (xResultIsSigned) - { - XS.Jump(xOverflowLabel); //too big - } - else - { - XS.Compare(EAX, 1); // only lowest bit is set, which is heighest of next - XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); - } - } - XS.Label(xOverflowLabel); - XS.Pop(EAX); // clear stack - Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); - XS.Label(xSuccessLabel); - } - - public static void CheckOverflowForLong(uint xResultSize, bool xSourceIsSigned, bool xResultIsSigned, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, string xSuccessLabel, string xOverflowLabel, string xPositiveLabel, string xNegativeLabel) - { - // long is - // low - // high - XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); // read high - if (xSourceIsSigned) - { - XS.ShiftRight(EAX, 31); // get highest bit of high to determine sign - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Equal, xPositiveLabel); - XS.Compare(EAX, 1); - XS.Jump(ConditionalTestEnum.Equal, xResultIsSigned ? xNegativeLabel : xOverflowLabel); - } - else - { - XS.Compare(EAX, 0); // as unsigned high must be positive - XS.Jump(ConditionalTestEnum.Equal, xPositiveLabel); - } - XS.Label(xOverflowLabel); - XS.Pop(EAX); //remove long from stack - XS.Pop(EAX); - Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); - - // Positive check - XS.Label(xPositiveLabel); - XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); // read high to refresh - XS.Set(EBX, ESP, sourceIsIndirect: true); // read low - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); - if(xResultSize == 4 && !xResultIsSigned) - { - XS.Jump(xSuccessLabel); - } - else - { - var v = xResultSize * 8; - if (xResultIsSigned) - { - v -= 1; - } - XS.ShiftRight(EBX, (byte)v); // now check if low does not overflow - XS.Compare(EBX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); - XS.Jump(xSuccessLabel); - } - - //Negative check - if (xSourceIsSigned) - { - XS.Label(xNegativeLabel); - if(!xResultIsSigned) - { - XS.Jump(xOverflowLabel); - } - XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); // read high to refresh - XS.Compare(EAX, 0xffff_ffff); // high should be fully set - XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); - XS.Set(EBX, ESP, sourceIsIndirect: true); // read low - XS.ShiftRight(EBX, (byte)(xResultSize * 8)); // now check if low does not overflow - XS.Not(EBX); - XS.Compare(EBX, 0); - XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); - } - - XS.Label(xSuccessLabel); - } - } - -} +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + class ConvOverflowChecks + { + public static void CheckOverflowForSmall(uint xResultSize, bool xSourceIsSigned, bool xResultIsSigned, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, string xSuccessLabel, string xOverflowLabel) + { + XS.Set(RAX, RSP, sourceIsIndirect: true); + // only look at bits which are part of result + // normally check that they are all either 0 or 1 + // if same size but casting between signed and unsigned, then first bit must be zero + byte bitCount = (byte)(xResultSize * 8 - 1); + XS.ShiftRight(RAX, bitCount); + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); + if (xSourceIsSigned) + { + if (xResultIsSigned) + { + XS.Not(RAX); // if negative then all must be 1s + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); + } + else + { + XS.Jump(xOverflowLabel); + } + } + else // source was unsigned + { + if (xResultIsSigned) + { + XS.Jump(xOverflowLabel); //too big + } + else + { + XS.Compare(RAX, 1); // only lowest bit is set, which is heighest of next + XS.Jump(ConditionalTestEnum.Equal, xSuccessLabel); + } + } + XS.Label(xOverflowLabel); + XS.Pop(RAX); // clear stack + Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); + XS.Label(xSuccessLabel); + } + + public static void CheckOverflowForLong(uint xResultSize, bool xSourceIsSigned, bool xResultIsSigned, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, string xSuccessLabel, string xOverflowLabel, string xPositiveLabel, string xNegativeLabel) + { + // long is + // low + // high + XS.Set(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: 4); // read high + if (xSourceIsSigned) + { + XS.ShiftRight(RAX, 31); // get highest bit of high to determine sign + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Equal, xPositiveLabel); + XS.Compare(RAX, 1); + XS.Jump(ConditionalTestEnum.Equal, xResultIsSigned ? xNegativeLabel : xOverflowLabel); + } + else + { + XS.Compare(RAX, 0); // as unsigned high must be positive + XS.Jump(ConditionalTestEnum.Equal, xPositiveLabel); + } + XS.Label(xOverflowLabel); + XS.Pop(RAX); //remove long from stack + XS.Pop(RAX); + Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); + + // Positive check + XS.Label(xPositiveLabel); + XS.Set(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: 4); // read high to refresh + XS.Set(RBX, RSP, sourceIsIndirect: true); // read low + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); + if(xResultSize == 4 && !xResultIsSigned) + { + XS.Jump(xSuccessLabel); + } + else + { + var v = xResultSize * 8; + if (xResultIsSigned) + { + v -= 1; + } + XS.ShiftRight(RBX, (byte)v); // now check if low does not overflow + XS.Compare(RBX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); + XS.Jump(xSuccessLabel); + } + + //Negative check + if (xSourceIsSigned) + { + XS.Label(xNegativeLabel); + if(!xResultIsSigned) + { + XS.Jump(xOverflowLabel); + } + XS.Set(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: 4); // read high to refresh + XS.Compare(RAX, 0xffff_ffff); // high should be fully set + XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); + XS.Set(RBX, RSP, sourceIsIndirect: true); // read low + XS.ShiftRight(RBX, (byte)(xResultSize * 8)); // now check if low does not overflow + XS.Not(RBX); + XS.Compare(RBX, 0); + XS.Jump(ConditionalTestEnum.NotEqual, xOverflowLabel); + } + + XS.Label(xSuccessLabel); + } + } + +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_I.cs b/source/Cosmos.IL2CPU/IL/Conv_I.cs index 09fdaec8a..d15db150a 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_I.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_I.cs @@ -1,37 +1,37 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Conv_I)] - public class Conv_I : ILOp - { - public Conv_I(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - - if (IsReferenceType(xSource)) - { - // todo: Stop GC tracking - XS.Add(ESP, SizeOfType(typeof(IntPtr))); - } - else if (IsPointer(xSource)) - { - // todo: Stop GC tracking - } - else - { - // todo: for x64, this should be Conv_I8, maybe create a common method for all conv.i ops? - Conv_I4.DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Conv_I)] + public class Conv_I : ILOp + { + public Conv_I(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + + if (IsReferenceType(xSource)) + { + // todo: Stop GC tracking + XS.Add(RSP, SizeOfType(typeof(IntPtr))); + } + else if (IsPointer(xSource)) + { + // todo: Stop GC tracking + } + else + { + // todo: for x64, this should be Conv_I8, maybe create a common method for all conv.i ops? + Conv_I4.DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_I1.cs b/source/Cosmos.IL2CPU/IL/Conv_I1.cs index 9edc003eb..6a2115c4d 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_I1.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_I1.cs @@ -1,84 +1,84 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to int8, pushing int32 on stack. - /// - [OpCode(ILOpCode.Code.Conv_I1)] - public class Conv_I1 : ILOp - { - public Conv_I1(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceSize = SizeOfType(xSource); - var xSourceIsFloat = TypeIsFloat(xSource); - - - DoExecute(xSourceSize, xSourceIsFloat, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - - public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - var xOverflowLabel = xBaseLabel + "Overflow"; - var xPositiveLabel = xBaseLabel + "Positive"; - var xNegativeLabel = xBaseLabel + "Negative"; - if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); - XS.MoveSignExtend(EAX, AL); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForSmall(1, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); - } - XS.Pop(EAX); - XS.MoveSignExtend(EAX, AL); - XS.Push(EAX); - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForLong(1, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); - } - XS.Pop(EAX); - XS.Add(ESP, 4); - XS.MoveSignExtend(EAX, AX); - XS.Push(EAX); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to int8, pushing int32 on stack. + /// + [OpCode(ILOpCode.Code.Conv_I1)] + public class Conv_I1 : ILOp + { + public Conv_I1(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceSize = SizeOfType(xSource); + var xSourceIsFloat = TypeIsFloat(xSource); + + + DoExecute(xSourceSize, xSourceIsFloat, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + + public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + var xOverflowLabel = xBaseLabel + "Overflow"; + var xPositiveLabel = xBaseLabel + "Positive"; + var xNegativeLabel = xBaseLabel + "Negative"; + if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.ConvertSS2SIAndTruncate(RAX, XMM0); + XS.MoveSignExtend(RAX, AL); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForSmall(1, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); + } + XS.Pop(RAX); + XS.MoveSignExtend(RAX, AL); + XS.Push(RAX); + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE2.ConvertSD2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForLong(1, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); + } + XS.Pop(RAX); + XS.Add(RSP, 4); + XS.MoveSignExtend(RAX, AX); + XS.Push(RAX); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I1.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_I2.cs b/source/Cosmos.IL2CPU/IL/Conv_I2.cs index 39557ab99..7a0041b9b 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_I2.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_I2.cs @@ -1,83 +1,83 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to int16, pushing int32 on stack. - /// - [OpCode(ILOpCode.Code.Conv_I2)] - public class Conv_I2 : ILOp - { - public Conv_I2(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceSize = SizeOfType(xSource); - var xSourceIsFloat = TypeIsFloat(xSource); - - DoExecute(xSourceSize, xSourceIsFloat, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - - public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - var xOverflowLabel = xBaseLabel + "Overflow"; - var xPositiveLabel = xBaseLabel + "Positive"; - var xNegativeLabel = xBaseLabel + "Negative"; - if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); - XS.MoveSignExtend(EAX, AX); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForSmall(2, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); - } - XS.Pop(EAX); - XS.MoveSignExtend(EAX, AX); - XS.Push(EAX); - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForLong(2, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); - } - XS.Pop(EAX); - XS.Add(ESP, 4); - XS.MoveSignExtend(EAX, AX); - XS.Push(EAX); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I2.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to int16, pushing int32 on stack. + /// + [OpCode(ILOpCode.Code.Conv_I2)] + public class Conv_I2 : ILOp + { + public Conv_I2(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceSize = SizeOfType(xSource); + var xSourceIsFloat = TypeIsFloat(xSource); + + DoExecute(xSourceSize, xSourceIsFloat, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + + public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + var xOverflowLabel = xBaseLabel + "Overflow"; + var xPositiveLabel = xBaseLabel + "Positive"; + var xNegativeLabel = xBaseLabel + "Negative"; + if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.ConvertSS2SIAndTruncate(RAX, XMM0); + XS.MoveSignExtend(RAX, AX); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForSmall(2, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); + } + XS.Pop(RAX); + XS.MoveSignExtend(RAX, AX); + XS.Push(RAX); + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE2.ConvertSD2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForLong(2, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); + } + XS.Pop(RAX); + XS.Add(RSP, 4); + XS.MoveSignExtend(RAX, AX); + XS.Push(RAX); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I2.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_I4.cs b/source/Cosmos.IL2CPU/IL/Conv_I4.cs index 4da0aa0e9..2a9d6dbaa 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_I4.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_I4.cs @@ -1,75 +1,75 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to int32, pushing int32 on stack. - /// - [OpCode(ILOpCode.Code.Conv_I4)] - public class Conv_I4 : ILOp - { - public Conv_I4(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - - public static void DoExecute(uint xSourceSize, bool aIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - var xOverflowLabel = xBaseLabel + "Overflow"; - var xPositiveLabel = xBaseLabel + "Positive"; - var xNegativeLabel = xBaseLabel + "Negative"; - if (xSourceSize <= 4) - { - if (aIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if(checkOverflow) - { - ConvOverflowChecks.CheckOverflowForSmall(4, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); - } - } - } - else if (xSourceSize <= 8) - { - if (aIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForLong(4, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); - } - XS.Pop(EAX); - XS.Add(ESP, 4); - XS.Push(EAX); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I4.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to int32, pushing int32 on stack. + /// + [OpCode(ILOpCode.Code.Conv_I4)] + public class Conv_I4 : ILOp + { + public Conv_I4(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + + public static void DoExecute(uint xSourceSize, bool aIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + var xOverflowLabel = xBaseLabel + "Overflow"; + var xPositiveLabel = xBaseLabel + "Positive"; + var xNegativeLabel = xBaseLabel + "Negative"; + if (xSourceSize <= 4) + { + if (aIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.ConvertSS2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if(checkOverflow) + { + ConvOverflowChecks.CheckOverflowForSmall(4, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); + } + } + } + else if (xSourceSize <= 8) + { + if (aIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE2.ConvertSD2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForLong(4, xSourceIsSigned, true, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); + } + XS.Pop(RAX); + XS.Add(RSP, 4); + XS.Push(RAX); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I4.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_I8.cs b/source/Cosmos.IL2CPU/IL/Conv_I8.cs index 4b14728ac..042e46e5b 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_I8.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_I8.cs @@ -1,79 +1,79 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to int64, pushing int64 on stack. - /// - [OpCode(ILOpCode.Code.Conv_I8)] - public class Conv_I8 : ILOp - { - public Conv_I8(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceSize = SizeOfType(xSource); - var xSourceIsFloat = TypeIsFloat(xSource); - - if (IsReferenceType(xSource)) - { - // todo: Stop GC tracking - XS.Add(ESP, SizeOfType(typeof(IntPtr))); - - // todo: x64 - XS.Pop(EAX); - XS.Push(0); - XS.Push(EAX); - } - else if (IsByRef(xSource)) - { - // todo: Stop GC tracking - throw new NotImplementedException($"Error compiling '{GetLabel(aMethod)}': conv.i8 not implemented for byref types!"); - } - else if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - /* - * Sadly for x86 there is no way using SSE to convert a float to an Int64... in x64 we could use ConvertPD2DQAndTruncate with - * x64 register as a destination... so this one of the few cases in which we need the legacy FPU! - */ - XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32); - XS.Sub(ESP, 4); - XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); - } - else - { - XS.Pop(EAX); - XS.SignExtendAX(RegisterSize.Int32); - XS.Push(EDX); - XS.Push(EAX); - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - /* - * Sadly for x86 there is no way using SSE to convert a double to an Int64... in x64 we could use ConvertPD2DQAndTruncate with - * x64 register as a destination... so only in this case we need the legacy FPU! - */ - XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64); - XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I8.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to int64, pushing int64 on stack. + /// + [OpCode(ILOpCode.Code.Conv_I8)] + public class Conv_I8 : ILOp + { + public Conv_I8(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceSize = SizeOfType(xSource); + var xSourceIsFloat = TypeIsFloat(xSource); + + if (IsReferenceType(xSource)) + { + // todo: Stop GC tracking + XS.Add(RSP, SizeOfType(typeof(IntPtr))); + + // todo: x64 + XS.Pop(RAX); + XS.Push(0); + XS.Push(RAX); + } + else if (IsByRef(xSource)) + { + // todo: Stop GC tracking + throw new NotImplementedException($"Error compiling '{GetLabel(aMethod)}': conv.i8 not implemented for byref types!"); + } + else if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + /* + * Sadly for x86 there is no way using SSE to convert a float to an Int64... in x64 we could use ConvertPD2DQAndTruncate with + * x64 register as a destination... so this one of the few cases in which we need the legacy FPU! + */ + XS.FPU.FloatLoad(RSP, destinationIsIndirect: true, size: RegisterSize.Long64); + XS.Sub(RSP, 4); + XS.FPU.IntStoreWithTruncate(RSP, isIndirect: true, size: RegisterSize.Long64); + } + else + { + XS.Pop(RAX); + XS.SignExtendAX(RegisterSize.Long64); + XS.Push(RDX); + XS.Push(RAX); + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + /* + * Sadly for x86 there is no way using SSE to convert a double to an Int64... in x64 we could use ConvertPD2DQAndTruncate with + * x64 register as a destination... so only in this case we need the legacy FPU! + */ + XS.FPU.FloatLoad(RSP, destinationIsIndirect: true, size: RegisterSize.Long64); + XS.FPU.IntStoreWithTruncate(RSP, isIndirect: true, size: RegisterSize.Long64); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_I8.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_Ovf_I8.cs b/source/Cosmos.IL2CPU/IL/Conv_Ovf_I8.cs index c41a1a4ca..b77541895 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_Ovf_I8.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_Ovf_I8.cs @@ -1,61 +1,61 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Conv_Ovf_I8)] - public class Conv_Ovf_I8 : ILOp - { - public Conv_Ovf_I8(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceSize = SizeOfType(xSource); - var xSourceIsFloat = TypeIsFloat(xSource); - DoExecute(xSourceSize, false, Assembler, aMethod,aOpCode); - } - - public static void DoExecute(uint xSourceSize, bool SourceIsSigned, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - switch (xSourceSize) - { - case 1: - case 2: - case 4: - XS.Pop(EAX); - XS.SignExtendAX(RegisterSize.Int32); - XS.Push(EDX); - XS.Push(EAX); - break; - case 8: - if (SourceIsSigned) - { - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.And(EAX, 0b1000000000000000000000000000); - XS.Compare(EAX, 0); - XS.Jump(XSharp.Assembler.x86.ConditionalTestEnum.Equal, xSuccessLabel); - XS.Pop(EAX); // remove long from stack - XS.Pop(EAX); - Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); - XS.Label(xSuccessLabel); - } - else - { - XS.Noop(); - } - break; - default: - throw new NotImplementedException(); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Conv_Ovf_I8)] + public class Conv_Ovf_I8 : ILOp + { + public Conv_Ovf_I8(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceSize = SizeOfType(xSource); + var xSourceIsFloat = TypeIsFloat(xSource); + DoExecute(xSourceSize, false, Assembler, aMethod,aOpCode); + } + + public static void DoExecute(uint xSourceSize, bool SourceIsSigned, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + switch (xSourceSize) + { + case 1: + case 2: + case 4: + XS.Pop(RAX); + XS.SignExtendAX(RegisterSize.Long64); + XS.Push(RDX); + XS.Push(RAX); + break; + case 8: + if (SourceIsSigned) + { + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.And(RAX, 0b1000000000000000000000000000); + XS.Compare(RAX, 0); + XS.Jump(XSharp.Assembler.x86.ConditionalTestEnum.Equal, xSuccessLabel); + XS.Pop(RAX); // remove long from stack + XS.Pop(RAX); + Call.DoExecute(assembler, aMethod, ExceptionHelperRefs.ThrowOverflowExceptionRef, aOpCode, xSuccessLabel, false); + XS.Label(xSuccessLabel); + } + else + { + XS.Noop(); + } + break; + default: + throw new NotImplementedException(); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_R4.cs b/source/Cosmos.IL2CPU/IL/Conv_R4.cs index ece4fc0a6..75d436eec 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_R4.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_R4.cs @@ -29,8 +29,8 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { if (xSourceSize <= 2 || TypeIsSigned(xSource)) { - XS.SSE.ConvertSI2SS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true); + XS.SSE.ConvertSI2SS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.MoveSS(RSP, XMM0, destinationIsIndirect: true); } else { @@ -42,9 +42,9 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { if (xSourceIsFloat) { - XS.SSE2.ConvertSD2SS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true); + XS.SSE2.ConvertSD2SS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(RSP, XMM0, destinationIsIndirect: true); } else { @@ -54,11 +54,11 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) * Again there is no SSE instruction in x86 to do this conversion as we need a 64 Bit register to do this! So we are forced * to use the legacy x87 FPU to do this operation. In x64 the SSE instruction ConvertSIQ2SS should exist. */ - XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64); - XS.Add(ESP, 4); + XS.FPU.IntLoad(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.Add(RSP, 4); /* This instruction is not needed FloatStoreAndPop does already the conversion */ // XS.SSE2.ConvertSD2SS(XMM0, ESP, sourceIsIndirect: true); - XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Int32); + XS.FPU.FloatStoreAndPop(RSP, isIndirect: true, size: RegisterSize.Long64); } else { diff --git a/source/Cosmos.IL2CPU/IL/Conv_R8.cs b/source/Cosmos.IL2CPU/IL/Conv_R8.cs index 7dc957c56..24a5bddae 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_R8.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_R8.cs @@ -27,17 +27,17 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { if (xSourceIsFloat) { - XS.SSE2.ConvertSS2SD(XMM0, ESP, sourceIsIndirect: true); - XS.Sub(ESP, 4); - XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true); + XS.SSE2.ConvertSS2SD(XMM0, RSP, sourceIsIndirect: true); + XS.Sub(RSP, 4); + XS.SSE2.MoveSD(RSP, XMM0, destinationIsIndirect: true); } else { if (xSourceSize <= 2 || TypeIsSigned(xSource)) { - XS.SSE2.ConvertSI2SD(XMM0, ESP, sourceIsIndirect: true); - XS.Sub(ESP, 4); - XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true); + XS.SSE2.ConvertSI2SD(XMM0, RSP, sourceIsIndirect: true); + XS.Sub(RSP, 4); + XS.SSE2.MoveSD(RSP, XMM0, destinationIsIndirect: true); } else { @@ -51,8 +51,8 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { if (TypeIsSigned(xSource)) { - XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64); - XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64); + XS.FPU.IntLoad(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.FPU.FloatStoreAndPop(RSP, isIndirect: true, size: RegisterSize.Long64); } else { diff --git a/source/Cosmos.IL2CPU/IL/Conv_R_Un.cs b/source/Cosmos.IL2CPU/IL/Conv_R_Un.cs index dfcfe0bda..8d354b9fb 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_R_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_R_Un.cs @@ -1,106 +1,106 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Converts the unsigned integer value on top of the evaluation stack to F (native float) it can be double or some FPU extended precision Floating Point - /// type as the weird 80 bit float of x87). For now we assume it to be always equal to double. - /// - [OpCode(ILOpCode.Code.Conv_R_Un)] - public class Conv_R_Un : ILOp - { - public Conv_R_Un(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xValue = aOpCode.StackPopTypes[0]; - var xValueIsFloat = TypeIsFloat(xValue); - var xValueSize = SizeOfType(xValue); - - if (!xValueIsFloat) - { - switch (xValueSize) - { - case 1: - case 2: - case 4: - /* - * Code generated by C# / Visual Studio 2015 - * mov eax,dword ptr [anInt] - * mov dword ptr [ebp-0E0h],eax - * cvtsi2sd xmm0,dword ptr [ebp-0E0h] - * mov ecx,dword ptr [ebp-0E0h] - * shr ecx,1Fh - * addsd xmm0,mmword ptr __xmm@41f00000000000000000000000000000 (01176B40h)[ecx*8] - * movsd mmword ptr [aDouble],xmm0 # This for now means to copy our converted double to ESP - */ - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset"; - - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.Set(EBP, EAX, destinationDisplacement: -0xE0, destinationIsIndirect: true); - XS.SSE2.ConvertSI2SD(XMM0, EBP, sourceDisplacement: -0xE0, sourceIsIndirect: true); - XS.Set(ECX, EBP, sourceDisplacement: -0xE0, sourceIsIndirect: true); - // OK now we put in ECX the last bit of our unsigned value, we call it "SIGN_BIT" but is a little improper... - XS.ShiftRight(ECX, 31); - /* - * if the 'SIGN_BIT' is 0 it means that our uint could have been placed in a normal int so ConvertSI2SD did already - * the right thing: we have finished - * if the value is 1 we need to do that addition with that weird constant to obtain the real value as double - */ - XS.Compare(ECX, 0x00); - XS.Jump(ConditionalTestEnum.Equal, LabelSign_Bit_Unset); - XS.LiteralCode(@"addsd xmm0, [__uint2double_const]"); - XS.Label(LabelSign_Bit_Unset); - // We have converted our value to double put it on ESP - // expand stack, that moved data is valid stack - XS.Sub(ESP, 4); - XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true); - break; - - case 8: - BaseLabel = GetLabel(aMethod, aOpCode) + "."; - LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset"; - - /* - * mov EAX, ESP + 4 - * fild qword ptr [esp] - * shr EAX, 31 - * cmp ESP, 0 - * jpe LabelSign_Bit_Unset - * LabelSign_Bit_Unset: - * fadd dword ptr __ulong2double_const2 - * fstp ESP - */ - // Save the high part of the ulong in EAX (we cannot move all of ESP as it has 64 bit size) - XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); - XS.FPU.IntLoad(ESP, isIndirect: true, size: RegisterSize.Long64); - XS.Test(EAX, EAX); - XS.Jump(ConditionalTestEnum.NotSign, LabelSign_Bit_Unset); - // If the sign is set we remove it using the constant __ulong2double_const4 - XS.LiteralCode(@"fadd dword [__ulong2double_const]"); - XS.Label(LabelSign_Bit_Unset); - // Convert the value to double and move it into the stack - XS.FPU.FloatStoreAndPop(ESP, isIndirect: true, size: RegisterSize.Long64); - break; - - default: - //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); - throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!"); - } - } - else - { - throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Converts the unsigned integer value on top of the evaluation stack to F (native float) it can be double or some FPU extended precision Floating Point + /// type as the weird 80 bit float of x87). For now we assume it to be always equal to double. + /// + [OpCode(ILOpCode.Code.Conv_R_Un)] + public class Conv_R_Un : ILOp + { + public Conv_R_Un(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xValue = aOpCode.StackPopTypes[0]; + var xValueIsFloat = TypeIsFloat(xValue); + var xValueSize = SizeOfType(xValue); + + if (!xValueIsFloat) + { + switch (xValueSize) + { + case 1: + case 2: + case 4: + /* + * Code generated by C# / Visual Studio 2015 + * mov eax,dword ptr [anInt] + * mov dword ptr [ebp-0E0h],eax + * cvtsi2sd xmm0,dword ptr [ebp-0E0h] + * mov ecx,dword ptr [ebp-0E0h] + * shr ecx,1Fh + * addsd xmm0,mmword ptr __xmm@41f00000000000000000000000000000 (01176B40h)[ecx*8] + * movsd mmword ptr [aDouble],xmm0 # This for now means to copy our converted double to ESP + */ + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset"; + + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.Set(RBP, RAX, destinationDisplacement: -0xE0, destinationIsIndirect: true); + XS.SSE2.ConvertSI2SD(XMM0, RBP, sourceDisplacement: -0xE0, sourceIsIndirect: true); + XS.Set(RCX, RBP, sourceDisplacement: -0xE0, sourceIsIndirect: true); + // OK now we put in ECX the last bit of our unsigned value, we call it "SIGN_BIT" but is a little improper... + XS.ShiftRight(RCX, 31); + /* + * if the 'SIGN_BIT' is 0 it means that our uint could have been placed in a normal int so ConvertSI2SD did already + * the right thing: we have finished + * if the value is 1 we need to do that addition with that weird constant to obtain the real value as double + */ + XS.Compare(RCX, 0x00); + XS.Jump(ConditionalTestEnum.Equal, LabelSign_Bit_Unset); + XS.LiteralCode(@"addsd xmm0, [__uint2double_const]"); + XS.Label(LabelSign_Bit_Unset); + // We have converted our value to double put it on ESP + // expand stack, that moved data is valid stack + XS.Sub(RSP, 4); + XS.SSE2.MoveSD(RSP, XMM0, destinationIsIndirect: true); + break; + + case 8: + BaseLabel = GetLabel(aMethod, aOpCode) + "."; + LabelSign_Bit_Unset = BaseLabel + "LabelSign_Bit_Unset"; + + /* + * mov EAX, ESP + 4 + * fild qword ptr [esp] + * shr EAX, 31 + * cmp ESP, 0 + * jpe LabelSign_Bit_Unset + * LabelSign_Bit_Unset: + * fadd dword ptr __ulong2double_const2 + * fstp ESP + */ + // Save the high part of the ulong in EAX (we cannot move all of ESP as it has 64 bit size) + XS.Set(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: 4); + XS.FPU.IntLoad(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.Test(RAX, RAX); + XS.Jump(ConditionalTestEnum.NotSign, LabelSign_Bit_Unset); + // If the sign is set we remove it using the constant __ulong2double_const4 + XS.LiteralCode(@"fadd dword [__ulong2double_const]"); + XS.Label(LabelSign_Bit_Unset); + // Convert the value to double and move it into the stack + XS.FPU.FloatStoreAndPop(RSP, isIndirect: true, size: RegisterSize.Long64); + break; + + default: + //EmitNotImplementedException( Assembler, GetServiceProvider(), "Conv_I: SourceSize " + xSource + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); + throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!"); + } + } + else + { + throw new NotImplementedException("Conv_R_Un with type " + xValue + " not supported!"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_U.cs b/source/Cosmos.IL2CPU/IL/Conv_U.cs index 1701c7fa6..ccd61395d 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_U.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_U.cs @@ -1,38 +1,38 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Conv_U)] - public class Conv_U : ILOp - { - public Conv_U(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - - - if (IsReferenceType(xSource)) - { - // todo: Stop GC tracking - XS.Add(ESP, SizeOfType(typeof(IntPtr))); - } - else if (IsPointer(xSource)) - { - // todo: Stop GC tracking - } - else - { - // todo: for x64, this should be Conv_U8, maybe create a common method for all conv.u ops? - Conv_U4.DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Conv_U)] + public class Conv_U : ILOp + { + public Conv_U(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + + + if (IsReferenceType(xSource)) + { + // todo: Stop GC tracking + XS.Add(RSP, SizeOfType(typeof(IntPtr))); + } + else if (IsPointer(xSource)) + { + // todo: Stop GC tracking + } + else + { + // todo: for x64, this should be Conv_U8, maybe create a common method for all conv.u ops? + Conv_U4.DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_U1.cs b/source/Cosmos.IL2CPU/IL/Conv_U1.cs index 575a4b97e..43101ae0b 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_U1.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_U1.cs @@ -1,82 +1,82 @@ -using System; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to unsigned int8, pushing int32 on stack. - /// - [OpCode(ILOpCode.Code.Conv_U1)] - public class Conv_U1 : ILOp - { - public Conv_U1(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceIsFloat = TypeIsFloat(xSource); - var xSourceSize = SizeOfType(xSource); - - DoExecute(xSourceIsFloat, xSourceSize, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - - public static void DoExecute(bool xSourceIsFloat, uint xSourceSize, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - var xOverflowLabel = xBaseLabel + "Overflow"; - var xPositiveLabel = xBaseLabel + "Positive"; - var xNegativeLabel = xBaseLabel + "Negative"; - if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); - XS.MoveZeroExtend(EAX, AL); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForSmall(1, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); - } - XS.Pop(EAX); - XS.MoveZeroExtend(EAX, AL); - XS.Push(EAX); - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForLong(1, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); - } - XS.Pop(EAX); - XS.Add(ESP, 4); - XS.MoveZeroExtend(EAX, AL); - XS.Push(EAX); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U1.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to unsigned int8, pushing int32 on stack. + /// + [OpCode(ILOpCode.Code.Conv_U1)] + public class Conv_U1 : ILOp + { + public Conv_U1(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceIsFloat = TypeIsFloat(xSource); + var xSourceSize = SizeOfType(xSource); + + DoExecute(xSourceIsFloat, xSourceSize, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + + public static void DoExecute(bool xSourceIsFloat, uint xSourceSize, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + var xOverflowLabel = xBaseLabel + "Overflow"; + var xPositiveLabel = xBaseLabel + "Positive"; + var xNegativeLabel = xBaseLabel + "Negative"; + if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.ConvertSS2SIAndTruncate(RAX, XMM0); + XS.MoveZeroExtend(RAX, AL); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForSmall(1, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); + } + XS.Pop(RAX); + XS.MoveZeroExtend(RAX, AL); + XS.Push(RAX); + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE2.ConvertSD2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForLong(1, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); + } + XS.Pop(RAX); + XS.Add(RSP, 4); + XS.MoveZeroExtend(RAX, AL); + XS.Push(RAX); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U1.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_U2.cs b/source/Cosmos.IL2CPU/IL/Conv_U2.cs index 491932a1c..512851f28 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_U2.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_U2.cs @@ -1,84 +1,84 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to unsigned int16, pushing int32 on stack. - /// - [OpCode(ILOpCode.Code.Conv_U2)] - public class Conv_U2 : ILOp - { - public Conv_U2(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceSize = SizeOfType(xSource); - var xSourceIsFloat = TypeIsFloat(xSource); - - DoExecute(xSourceSize, xSourceIsFloat, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - - public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - var xOverflowLabel = xBaseLabel + "Overflow"; - var xPositiveLabel = xBaseLabel + "Positive"; - var xNegativeLabel = xBaseLabel + "Negative"; - if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); - XS.MoveZeroExtend(EAX, AX); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForSmall(2, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); - } - XS.Pop(EAX); - XS.MoveZeroExtend(EAX, AX); - XS.Push(EAX); - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); - XS.MoveZeroExtend(EAX, AX); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForLong(2, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); - } - XS.Pop(EAX); - XS.Add(ESP, 4); - XS.MoveZeroExtend(EAX, AX); - XS.Push(EAX); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U2.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to unsigned int16, pushing int32 on stack. + /// + [OpCode(ILOpCode.Code.Conv_U2)] + public class Conv_U2 : ILOp + { + public Conv_U2(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceSize = SizeOfType(xSource); + var xSourceIsFloat = TypeIsFloat(xSource); + + DoExecute(xSourceSize, xSourceIsFloat, TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + + public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + var xOverflowLabel = xBaseLabel + "Overflow"; + var xPositiveLabel = xBaseLabel + "Positive"; + var xNegativeLabel = xBaseLabel + "Negative"; + if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.ConvertSS2SIAndTruncate(RAX, XMM0); + XS.MoveZeroExtend(RAX, AX); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForSmall(2, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); + } + XS.Pop(RAX); + XS.MoveZeroExtend(RAX, AX); + XS.Push(RAX); + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE2.ConvertSD2SIAndTruncate(RAX, XMM0); + XS.MoveZeroExtend(RAX, AX); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForLong(2, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); + } + XS.Pop(RAX); + XS.Add(RSP, 4); + XS.MoveZeroExtend(RAX, AX); + XS.Push(RAX); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U2.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_U4.cs b/source/Cosmos.IL2CPU/IL/Conv_U4.cs index 41b03c6db..012375ccd 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_U4.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_U4.cs @@ -1,75 +1,75 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to unsigned int32, pushing int32 on stack. - /// - [OpCode(ILOpCode.Code.Conv_U4)] - public class Conv_U4 : ILOp - { - public Conv_U4(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); - } - - public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - var xOverflowLabel = xBaseLabel + "Overflow"; - var xPositiveLabel = xBaseLabel + "Positive"; - var xNegativeLabel = xBaseLabel + "Negative"; - if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.ConvertSS2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForSmall(4, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); - } - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE2.ConvertSD2SIAndTruncate(EAX, XMM0); - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - if (checkOverflow) - { - ConvOverflowChecks.CheckOverflowForLong(4, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); - } - XS.Pop(EAX); - XS.Add(ESP, 4); - XS.Push(EAX); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U4.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to unsigned int32, pushing int32 on stack. + /// + [OpCode(ILOpCode.Code.Conv_U4)] + public class Conv_U4 : ILOp + { + public Conv_U4(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + DoExecute(SizeOfType(xSource), TypeIsFloat(xSource), TypeIsSigned(xSource), false, Assembler, aMethod, aOpCode); + } + + public static void DoExecute(uint xSourceSize, bool xSourceIsFloat, bool xSourceIsSigned, bool checkOverflow, Assembler assembler, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + var xOverflowLabel = xBaseLabel + "Overflow"; + var xPositiveLabel = xBaseLabel + "Positive"; + var xNegativeLabel = xBaseLabel + "Negative"; + if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.ConvertSS2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForSmall(4, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel); + } + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE2.ConvertSD2SIAndTruncate(RAX, XMM0); + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + if (checkOverflow) + { + ConvOverflowChecks.CheckOverflowForLong(4, xSourceIsSigned, false, assembler, aMethod, aOpCode, xSuccessLabel, xOverflowLabel, xPositiveLabel, xNegativeLabel); + } + XS.Pop(RAX); + XS.Add(RSP, 4); + XS.Push(RAX); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U4.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Conv_U8.cs b/source/Cosmos.IL2CPU/IL/Conv_U8.cs index 74f2f7bc2..cd5116b46 100644 --- a/source/Cosmos.IL2CPU/IL/Conv_U8.cs +++ b/source/Cosmos.IL2CPU/IL/Conv_U8.cs @@ -1,77 +1,77 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Convert to unsigned int64, pushing int64 on stack. - /// - [OpCode(ILOpCode.Code.Conv_U8)] - public class Conv_U8 : ILOp - { - public Conv_U8(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xSource = aOpCode.StackPopTypes[0]; - var xSourceSize = SizeOfType(xSource); - var xSourceIsFloat = TypeIsFloat(xSource); - - DoExecute(aMethod, xSource, xSourceSize, xSourceIsFloat); - } - - public static void DoExecute(Il2cpuMethodInfo aMethod, Type xSource, uint xSourceSize, bool xSourceIsFloat) - { - if (IsReferenceType(xSource)) - { - // todo: Stop GC tracking - XS.Add(ESP, SizeOfType(typeof(UIntPtr))); - - // todo: x64 - XS.Pop(EAX); - XS.Push(0); - XS.Push(EAX); - } - else if (IsByRef(xSource)) - { - // todo: Stop GC tracking - throw new NotImplementedException($"Error compiling '{GetLabel(aMethod)}': conv.u8 not implemented for byref types!"); - } - else if (xSourceSize <= 4) - { - if (xSourceIsFloat) - { - XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Int32); - XS.Sub(ESP, 4); - XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); - } - else - { - XS.Pop(EAX); - XS.Push(0); - XS.Push(EAX); - } - } - else if (xSourceSize <= 8) - { - if (xSourceIsFloat) - { - XS.FPU.FloatLoad(ESP, destinationIsIndirect: true, size: RegisterSize.Long64); - /* The sign of the value should not be changed a negative value is simply converted to its corresponding ulong value */ - //XS.FPU.FloatAbs(); - XS.FPU.IntStoreWithTruncate(ESP, isIndirect: true, size: RegisterSize.Long64); - } - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U8.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Convert to unsigned int64, pushing int64 on stack. + /// + [OpCode(ILOpCode.Code.Conv_U8)] + public class Conv_U8 : ILOp + { + public Conv_U8(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xSource = aOpCode.StackPopTypes[0]; + var xSourceSize = SizeOfType(xSource); + var xSourceIsFloat = TypeIsFloat(xSource); + + DoExecute(aMethod, xSource, xSourceSize, xSourceIsFloat); + } + + public static void DoExecute(Il2cpuMethodInfo aMethod, Type xSource, uint xSourceSize, bool xSourceIsFloat) + { + if (IsReferenceType(xSource)) + { + // todo: Stop GC tracking + XS.Add(RSP, SizeOfType(typeof(UIntPtr))); + + // todo: x64 + XS.Pop(RAX); + XS.Push(0); + XS.Push(RAX); + } + else if (IsByRef(xSource)) + { + // todo: Stop GC tracking + throw new NotImplementedException($"Error compiling '{GetLabel(aMethod)}': conv.u8 not implemented for byref types!"); + } + else if (xSourceSize <= 4) + { + if (xSourceIsFloat) + { + XS.FPU.FloatLoad(RSP, destinationIsIndirect: true, size: RegisterSize.Long64); + XS.Sub(RSP, 4); + XS.FPU.IntStoreWithTruncate(RSP, isIndirect: true, size: RegisterSize.Long64); + } + else + { + XS.Pop(RAX); + XS.Push(0); + XS.Push(RAX); + } + } + else if (xSourceSize <= 8) + { + if (xSourceIsFloat) + { + XS.FPU.FloatLoad(RSP, destinationIsIndirect: true, size: RegisterSize.Long64); + /* The sign of the value should not be changed a negative value is simply converted to its corresponding ulong value */ + //XS.FPU.FloatAbs(); + XS.FPU.IntStoreWithTruncate(RSP, isIndirect: true, size: RegisterSize.Long64); + } + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Conv_U8.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Cpblk.cs b/source/Cosmos.IL2CPU/IL/Cpblk.cs index ec39db976..195a9e014 100644 --- a/source/Cosmos.IL2CPU/IL/Cpblk.cs +++ b/source/Cosmos.IL2CPU/IL/Cpblk.cs @@ -1,26 +1,26 @@ -using XSharp; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Cpblk)] - public class Cpblk : ILOp - { - public Cpblk(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - // destination address - XS.Pop(EDI); - // source address - XS.Pop(ESI); - // byte count - XS.Pop(ECX); - - new Movs { Prefixes = InstructionPrefixes.Repeat, Size = 8 }; - } - } -} +using XSharp; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Cpblk)] + public class Cpblk : ILOp + { + public Cpblk(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + // destination address + XS.Pop(RDI); + // source address + XS.Pop(RSI); + // byte count + XS.Pop(RCX); + + new Movs { Prefixes = InstructionPrefixes.Repeat, Size = 8 }; + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Div.cs b/source/Cosmos.IL2CPU/IL/Div.cs index fa8dd3528..664f1431f 100644 --- a/source/Cosmos.IL2CPU/IL/Div.cs +++ b/source/Cosmos.IL2CPU/IL/Div.cs @@ -1,197 +1,197 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Div)] - public class Div : ILOp - { - public Div(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); - var xIsFloat = TypeIsFloat(xStackItem); - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; - - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div.cs->Error: StackSize > 8 not supported"); - } - else if (xSize > 4) - { - if (xIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.DivSD(XMM1, XMM0); - XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true); - } - else - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LabelShiftRight = BaseLabel + "ShiftRightLoop"; - string LabelNoLoop = BaseLabel + "NoLoop"; - string LabelEnd = BaseLabel + "End"; - - // divisor - // low - XS.Pop(ESI); - // high - XS.Pop(EDI); - - XS.Xor(EAX, EAX); - XS.Or(EAX, ESI); - XS.Or(EAX, EDI); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - // dividend - // low - XS.Pop(EAX); - // high - XS.Pop(EDX); - - // set flags - XS.Or(EDI, EDI); - // if high dword of divisor is already zero, we dont need the loop - XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); - - // set ecx to zero for counting the shift operations - XS.Xor(ECX, ECX); - - // push most significant bit of result - XS.Set(EBX, EDI); - XS.Xor(EBX, EDX); - XS.Push(EBX); - - XS.Compare(EDI, 0x80000000); - XS.Jump(ConditionalTestEnum.Below, BaseLabel + "divisor_no_neg"); - - XS.Negate(ESI); - XS.AddWithCarry(EDI, 0); - XS.Negate(EDI); - - XS.Label(BaseLabel + "divisor_no_neg"); - - XS.Compare(EDX, 0x80000000); - XS.Jump(ConditionalTestEnum.Below, BaseLabel + "dividend_no_neg"); - - XS.Negate(EAX); - XS.AddWithCarry(EDX, 0); - XS.Negate(EDX); - - XS.Label(BaseLabel + "dividend_no_neg"); - - XS.Label(LabelShiftRight); - - // shift divisor 1 bit right - XS.ShiftRightDouble(ESI, EDI, 1); - XS.ShiftRight(EDI, 1); - - // increment shift counter - XS.Increment(ECX); - - // set flags - //XS.Or(EDI, EDI); - XS.Set(EBX, ESI); - XS.And(EBX, 0x80000000); - XS.Or(EBX, EDI); - // loop while high dword of divisor is not zero or most significant bit of low dword of divisor is set - XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); - - // shift the dividend now in one step - XS.ShiftRightDouble(EAX, EDX, CL); - // shift dividend CL bits right - XS.ShiftRight(EDX, CL); - - // so we shifted both, so we have near the same relation as original values - // divide this - XS.IntegerDivide(ESI); - - // pop most significant bit of result - XS.Pop(EBX); - - XS.Compare(EBX, 0x80000000); - XS.Jump(ConditionalTestEnum.Below, BaseLabel + "_result_no_neg"); - - XS.Negate(EAX); - - XS.Label(BaseLabel + "_result_no_neg"); - - // sign extend - XS.SignExtendAX(RegisterSize.Int32); - - // save result to stack - XS.Push(EDX); - XS.Push(EAX); - - //TODO: implement proper derivation correction and overflow detection - - XS.Jump(LabelEnd); - - XS.Label(LabelNoLoop); - // save high dividend - XS.Set(ECX, EAX); - XS.Set(EAX, EDX); - - // extend that sign is in edx - XS.SignExtendAX(RegisterSize.Int32); - // divide high part - XS.IntegerDivide(ESI); - // save high result - XS.Push(EAX); - XS.Set(EAX, ECX); - // divide low part - XS.Divide(ESI); - // save low result - XS.Push(EAX); - - XS.Label(LabelEnd); - } - } - else - { - if (xIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.DivSS(XMM1, XMM0); - XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true); - } - else - { - XS.Pop(ECX); - - XS.Test(ECX, ECX); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - XS.Pop(EAX); - - XS.SignExtendAX(RegisterSize.Int32); - - XS.IntegerDivide(ECX); - XS.Push(EAX); - } - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Div)] + public class Div : ILOp + { + public Div(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); + var xIsFloat = TypeIsFloat(xStackItem); + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; + + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div.cs->Error: StackSize > 8 not supported"); + } + else if (xSize > 4) + { + if (xIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.DivSD(XMM1, XMM0); + XS.SSE2.MoveSD(RSP, XMM1, destinationIsIndirect: true); + } + else + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LabelShiftRight = BaseLabel + "ShiftRightLoop"; + string LabelNoLoop = BaseLabel + "NoLoop"; + string LabelEnd = BaseLabel + "End"; + + // divisor + // low + XS.Pop(RSI); + // high + XS.Pop(RDI); + + XS.Xor(RAX, RAX); + XS.Or(RAX, RSI); + XS.Or(RAX, RDI); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + // dividend + // low + XS.Pop(RAX); + // high + XS.Pop(RDX); + + // set flags + XS.Or(RDI, RDI); + // if high dword of divisor is already zero, we dont need the loop + XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); + + // set ecx to zero for counting the shift operations + XS.Xor(RCX, RCX); + + // push most significant bit of result + XS.Set(RBX, RDI); + XS.Xor(RBX, RDX); + XS.Push(RBX); + + XS.Compare(RDI, 0x80000000); + XS.Jump(ConditionalTestEnum.Below, BaseLabel + "divisor_no_neg"); + + XS.Negate(RSI); + XS.AddWithCarry(RDI, 0); + XS.Negate(RDI); + + XS.Label(BaseLabel + "divisor_no_neg"); + + XS.Compare(RDX, 0x80000000); + XS.Jump(ConditionalTestEnum.Below, BaseLabel + "dividend_no_neg"); + + XS.Negate(RAX); + XS.AddWithCarry(RDX, 0); + XS.Negate(RDX); + + XS.Label(BaseLabel + "dividend_no_neg"); + + XS.Label(LabelShiftRight); + + // shift divisor 1 bit right + XS.ShiftRightDouble(RSI, RDI, 1); + XS.ShiftRight(RDI, 1); + + // increment shift counter + XS.Increment(RCX); + + // set flags + //XS.Or(EDI, EDI); + XS.Set(RBX, RSI); + XS.And(RBX, 0x80000000); + XS.Or(RBX, RDI); + // loop while high dword of divisor is not zero or most significant bit of low dword of divisor is set + XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); + + // shift the dividend now in one step + XS.ShiftRightDouble(RAX, RDX, CL); + // shift dividend CL bits right + XS.ShiftRight(RDX, CL); + + // so we shifted both, so we have near the same relation as original values + // divide this + XS.IntegerDivide(RSI); + + // pop most significant bit of result + XS.Pop(RBX); + + XS.Compare(RBX, 0x80000000); + XS.Jump(ConditionalTestEnum.Below, BaseLabel + "_result_no_neg"); + + XS.Negate(RAX); + + XS.Label(BaseLabel + "_result_no_neg"); + + // sign extend + XS.SignExtendAX(RegisterSize.Long64); + + // save result to stack + XS.Push(RDX); + XS.Push(RAX); + + //TODO: implement proper derivation correction and overflow detection + + XS.Jump(LabelEnd); + + XS.Label(LabelNoLoop); + // save high dividend + XS.Set(RCX, RAX); + XS.Set(RAX, RDX); + + // extend that sign is in edx + XS.SignExtendAX(RegisterSize.Long64); + // divide high part + XS.IntegerDivide(RSI); + // save high result + XS.Push(RAX); + XS.Set(RAX, RCX); + // divide low part + XS.Divide(RSI); + // save low result + XS.Push(RAX); + + XS.Label(LabelEnd); + } + } + else + { + if (xIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.DivSS(XMM1, XMM0); + XS.SSE.MoveSS(RSP, XMM1, destinationIsIndirect: true); + } + else + { + XS.Pop(RCX); + + XS.Test(RCX, RCX); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + XS.Pop(RAX); + + XS.SignExtendAX(RegisterSize.Long64); + + XS.IntegerDivide(RCX); + XS.Push(RAX); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Div_Un.cs b/source/Cosmos.IL2CPU/IL/Div_Un.cs index 0de75881a..5f4e1b3a1 100644 --- a/source/Cosmos.IL2CPU/IL/Div_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Div_Un.cs @@ -1,141 +1,141 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -/* Div.Un is unsigned integer division so the valid input values are uint / ulong and the result is always expressed as unsigned */ -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Div_Un)] - public class Div_Un : ILOp - { - public Div_Un(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; - - if (TypeIsFloat(xStackItem)) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Div_Un.cs->Error: Expected unsigned integer operands but got float!"); - } - - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div_Un.cs->Error: StackSize > 8 not supported"); - } - else if (xSize > 4) - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LabelShiftRight = BaseLabel + "ShiftRightLoop"; - string LabelNoLoop = BaseLabel + "NoLoop"; - string LabelEnd = BaseLabel + "End"; - - // divisor - // low - XS.Pop(ESI); - // high - XS.Pop(EDI); - - XS.Xor(EAX, EAX); - XS.Or(EAX, ESI); - XS.Or(EAX, EDI); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - // dividend - // low - XS.Pop(EAX); - // high - XS.Pop(EDX); - - // set flags - XS.Or(EDI, EDI); - // if high dword of divisor is already zero, we dont need the loop - XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); - - // set ecx to zero for counting the shift operations - XS.Xor(ECX, ECX); - - XS.Label(LabelShiftRight); - - // shift divisor 1 bit right - XS.ShiftRightDouble(ESI, EDI, 1); - XS.ShiftRight(EDI, 1); - - // increment shift counter - XS.Increment(ECX); - - // set flags - XS.Or(EDI, EDI); - // loop while high dword of divisor till it is zero - XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); - - // shift the dividend now in one step - // shift dividend CL bits right - XS.ShiftRightDouble(EAX, EDX, CL); - XS.ShiftRight(EDX, CL); - - // so we shifted both, so we have near the same relation as original values - // divide this - XS.Divide(ESI); - - // save result to stack - XS.Push(0); - XS.Push(EAX); - - //TODO: implement proper derivation correction and overflow detection - - XS.Jump(LabelEnd); - - XS.Label(LabelNoLoop); - - //save high dividend - XS.Set(ECX, EAX); - XS.Set(EAX, EDX); - // zero EDX, so that high part is zero -> reduce overflow case - XS.Xor(EDX, EDX); - // divide high part - XS.Divide(ESI); - // save high result - XS.Push(EAX); - XS.Set(EAX, ECX); - // divide low part - XS.Divide(ESI); - // save low result - XS.Push(EAX); - - XS.Label(LabelEnd); - } - else - { - XS.Pop(ECX); - - XS.Test(ECX, ECX); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - XS.Pop(EAX); - - XS.Xor(EDX, EDX); - - XS.Divide(ECX); - XS.Push(EAX); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +/* Div.Un is unsigned integer division so the valid input values are uint / ulong and the result is always expressed as unsigned */ +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Div_Un)] + public class Div_Un : ILOp + { + public Div_Un(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; + + if (TypeIsFloat(xStackItem)) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Div_Un.cs->Error: Expected unsigned integer operands but got float!"); + } + + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Div_Un.cs->Error: StackSize > 8 not supported"); + } + else if (xSize > 4) + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LabelShiftRight = BaseLabel + "ShiftRightLoop"; + string LabelNoLoop = BaseLabel + "NoLoop"; + string LabelEnd = BaseLabel + "End"; + + // divisor + // low + XS.Pop(RSI); + // high + XS.Pop(RDI); + + XS.Xor(RAX, RAX); + XS.Or(RAX, RSI); + XS.Or(RAX, RDI); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + // dividend + // low + XS.Pop(RAX); + // high + XS.Pop(RDX); + + // set flags + XS.Or(RDI, RDI); + // if high dword of divisor is already zero, we dont need the loop + XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); + + // set ecx to zero for counting the shift operations + XS.Xor(RCX, RCX); + + XS.Label(LabelShiftRight); + + // shift divisor 1 bit right + XS.ShiftRightDouble(RSI, RDI, 1); + XS.ShiftRight(RDI, 1); + + // increment shift counter + XS.Increment(RCX); + + // set flags + XS.Or(RDI, RDI); + // loop while high dword of divisor till it is zero + XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); + + // shift the dividend now in one step + // shift dividend CL bits right + XS.ShiftRightDouble(RAX, RDX, CL); + XS.ShiftRight(RDX, CL); + + // so we shifted both, so we have near the same relation as original values + // divide this + XS.Divide(RSI); + + // save result to stack + XS.Push(0); + XS.Push(RAX); + + //TODO: implement proper derivation correction and overflow detection + + XS.Jump(LabelEnd); + + XS.Label(LabelNoLoop); + + //save high dividend + XS.Set(RCX, RAX); + XS.Set(RAX, RDX); + // zero EDX, so that high part is zero -> reduce overflow case + XS.Xor(RDX, RDX); + // divide high part + XS.Divide(RSI); + // save high result + XS.Push(RAX); + XS.Set(RAX, RCX); + // divide low part + XS.Divide(RSI); + // save low result + XS.Push(RAX); + + XS.Label(LabelEnd); + } + else + { + XS.Pop(RCX); + + XS.Test(RCX, RCX); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + XS.Pop(RAX); + + XS.Xor(RDX, RDX); + + XS.Divide(RCX); + XS.Push(RAX); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Dup.cs b/source/Cosmos.IL2CPU/IL/Dup.cs index 8cef22ab8..3ed9d146a 100644 --- a/source/Cosmos.IL2CPU/IL/Dup.cs +++ b/source/Cosmos.IL2CPU/IL/Dup.cs @@ -1,29 +1,29 @@ - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Dup)] - public class Dup : ILOp - { - public Dup(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSize = SizeOfType(xStackContent); - var StackSize = (int)(xStackContentSize / 4 + (xStackContentSize % 4 == 0 ? 0 : 1)); - - for (int i = StackSize; i > 0; i--) - { - XS.Push(ESP, true, (StackSize - 1) * 4); - //new CPUx86.Push { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)((StackSize - 1) * 4) }; - } - } - - } -} + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Dup)] + public class Dup : ILOp + { + public Dup(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSize = SizeOfType(xStackContent); + var StackSize = (int)(xStackContentSize / 4 + (xStackContentSize % 4 == 0 ? 0 : 1)); + + for (int i = StackSize; i > 0; i--) + { + XS.Push(RSP, true, (StackSize - 1) * 4); + //new CPUx86.Push { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = (int)((StackSize - 1) * 4) }; + } + } + + } +} diff --git a/source/Cosmos.IL2CPU/IL/Endfinally.cs b/source/Cosmos.IL2CPU/IL/Endfinally.cs index a577d60d4..cbfb79066 100644 --- a/source/Cosmos.IL2CPU/IL/Endfinally.cs +++ b/source/Cosmos.IL2CPU/IL/Endfinally.cs @@ -1,24 +1,24 @@ - -using Cosmos.IL2CPU.Extensions; -using XSharp; -using CPUx86 = XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Endfinally)] - public class Endfinally : ILOp - { - public Endfinally(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - string leaveAddressVariableName = $"{aMethod.MethodBase.GetFullName()}_LeaveAddress_{aOpCode.CurrentExceptionRegion.HandlerOffset:X2}"; - XS.DataMember(leaveAddressVariableName, 0); - XS.Set(EAX, leaveAddressVariableName); - new CPUx86.Jump { DestinationReg = EAX, DestinationIsIndirect = true }; - } - } -} + +using Cosmos.IL2CPU.Extensions; +using XSharp; +using CPUx86 = XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Endfinally)] + public class Endfinally : ILOp + { + public Endfinally(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + string leaveAddressVariableName = $"{aMethod.MethodBase.GetFullName()}_LeaveAddress_{aOpCode.CurrentExceptionRegion.HandlerOffset:X2}"; + XS.DataMember(leaveAddressVariableName, 0); + XS.Set(RAX, leaveAddressVariableName); + new CPUx86.Jump { DestinationReg = RAX, DestinationIsIndirect = true }; + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Initblk.cs b/source/Cosmos.IL2CPU/IL/Initblk.cs index 1f5e0fb0f..59277d9e6 100644 --- a/source/Cosmos.IL2CPU/IL/Initblk.cs +++ b/source/Cosmos.IL2CPU/IL/Initblk.cs @@ -1,44 +1,44 @@ -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Initblk)] - public class Initblk : ILOp - { - public Initblk(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; - - // size - XS.Pop(ECX); - // value - XS.Pop(EBX); - // address - XS.Pop(EDI); - - XS.Compare(ECX, 0); - XS.Jump(ConditionalTestEnum.Equal, xEndLabel); - - XS.Set(EDI, BL, destinationIsIndirect: true); - - XS.Compare(ECX, 1); - XS.Jump(ConditionalTestEnum.Equal, xEndLabel); - - XS.Set(ESI, EDI); - XS.Increment(EDI); - XS.Decrement(ECX); - - new Movs { Prefixes = InstructionPrefixes.Repeat, Size = 8 }; - - XS.Label(xEndLabel); - } - } -} +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Initblk)] + public class Initblk : ILOp + { + public Initblk(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xEndLabel = GetLabel(aMethod, aOpCode) + ".End"; + + // size + XS.Pop(RCX); + // value + XS.Pop(RBX); + // address + XS.Pop(RDI); + + XS.Compare(RCX, 0); + XS.Jump(ConditionalTestEnum.Equal, xEndLabel); + + XS.Set(RDI, BL, destinationIsIndirect: true); + + XS.Compare(RCX, 1); + XS.Jump(ConditionalTestEnum.Equal, xEndLabel); + + XS.Set(RSI, RDI); + XS.Increment(RDI); + XS.Decrement(RCX); + + new Movs { Prefixes = InstructionPrefixes.Repeat, Size = 8 }; + + XS.Label(xEndLabel); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Initobj.cs b/source/Cosmos.IL2CPU/IL/Initobj.cs index 1227324cd..af35fe3f4 100644 --- a/source/Cosmos.IL2CPU/IL/Initobj.cs +++ b/source/Cosmos.IL2CPU/IL/Initobj.cs @@ -1,59 +1,59 @@ -using System; -using IL2CPU.API; -using XSharp; -using static XSharp.XSRegisters; -using CPUx86 = XSharp.Assembler.x86; -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Initobj)] - public class Initobj : ILOp - { - public Initobj(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - Execute(aMethod, aOpCode); - - } - - public void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool aFromNewObj = false) - { - Type mType = ((ILOpCodes.OpType)aOpCode).Value; - uint mObjSize = SizeOfType(mType); - - XS.Pop(EAX); - - for (int i = 0; i < mObjSize / 4; i++) - { - XS.Set(EAX, 0, destinationDisplacement: i * 4, size: RegisterSize.Int32); - } - switch (mObjSize % 4) - { - case 1: - { - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4), SourceValue = 0, Size = 8 }; - break; - } - case 2: - { - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4), SourceValue = 0, Size = 16 }; - break; - } - case 3: - { - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4), SourceValue = 0, Size = 8 }; - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4 + 1), SourceValue = 0, Size = 16 }; - break; - } - case 0: - break; - default: - { - throw new NotImplementedException("Remainder size " + mObjSize % 4 + " not supported yet! (Type = '" + mType.FullName + "')"); - } - } - } - } -} +using System; +using IL2CPU.API; +using XSharp; +using static XSharp.XSRegisters; +using CPUx86 = XSharp.Assembler.x86; +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Initobj)] + public class Initobj : ILOp + { + public Initobj(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + Execute(aMethod, aOpCode); + + } + + public void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool aFromNewObj = false) + { + Type mType = ((ILOpCodes.OpType)aOpCode).Value; + uint mObjSize = SizeOfType(mType); + + XS.Pop(RAX); + + for (int i = 0; i < mObjSize / 4; i++) + { + XS.Set(RAX, 0, destinationDisplacement: i * 4, size: RegisterSize.Long64); + } + switch (mObjSize % 4) + { + case 1: + { + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4), SourceValue = 0, Size = 8 }; + break; + } + case 2: + { + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4), SourceValue = 0, Size = 16 }; + break; + } + case 3: + { + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4), SourceValue = 0, Size = 8 }; + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.EAX, DestinationIsIndirect = true, DestinationDisplacement = (int)(mObjSize / 4 * 4 + 1), SourceValue = 0, Size = 16 }; + break; + } + case 0: + break; + default: + { + throw new NotImplementedException("Remainder size " + mObjSize % 4 + " not supported yet! (Type = '" + mType.FullName + "')"); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Isinst.cs b/source/Cosmos.IL2CPU/IL/Isinst.cs index f3d7e9193..c459a879a 100644 --- a/source/Cosmos.IL2CPU/IL/Isinst.cs +++ b/source/Cosmos.IL2CPU/IL/Isinst.cs @@ -1,57 +1,57 @@ -using System; - -using Cosmos.IL2CPU.ILOpCodes; -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Tests whether an object reference (type O) is an instance of a particular class. - /// - [OpCode(ILOpCode.Code.Isinst)] - public class Isinst : ILOp - { - public Isinst(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - OpType xType = (OpType)aOpCode; - string xTypeID = GetTypeIDLabel(xType.Value); - string xCurrentMethodLabel = GetLabel(aMethod, aOpCode); - string xReturnNullLabel = xCurrentMethodLabel + "_ReturnNull"; - string xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; - string xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); - - XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); - - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Zero, xReturnNullLabel); - - XS.Push(EAX, isIndirect: true); - XS.Push(xTypeID, isIndirect: true); - XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); - - Call.DoExecute(Assembler, aMethod, VTablesImplRefs.IsInstanceRef, - aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); - - XS.Label(xAfterIsInstanceCallLabel); - - XS.Pop(EAX); - XS.Compare(EAX, 0); - XS.Jump(ConditionalTestEnum.Equal, xReturnNullLabel); - XS.Jump(xNextPositionLabel); - - XS.Label(xReturnNullLabel); - - XS.Add(ESP, 8); - XS.Push(0); - XS.Push(0); - } - } -} +using System; + +using Cosmos.IL2CPU.ILOpCodes; +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Tests whether an object reference (type O) is an instance of a particular class. + /// + [OpCode(ILOpCode.Code.Isinst)] + public class Isinst : ILOp + { + public Isinst(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + OpType xType = (OpType)aOpCode; + string xTypeID = GetTypeIDLabel(xType.Value); + string xCurrentMethodLabel = GetLabel(aMethod, aOpCode); + string xReturnNullLabel = xCurrentMethodLabel + "_ReturnNull"; + string xAfterIsInstanceCallLabel = xCurrentMethodLabel + "_After_IsInstance_Call"; + string xNextPositionLabel = GetLabel(aMethod, aOpCode.NextPosition); + + XS.Set(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: 4); + + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Zero, xReturnNullLabel); + + XS.Push(RAX, isIndirect: true); + XS.Push(xTypeID, isIndirect: true); + XS.Push(Convert.ToUInt32(xType.Value.IsInterface)); + + Call.DoExecute(Assembler, aMethod, VTablesImplRefs.IsInstanceRef, + aOpCode, xCurrentMethodLabel, xAfterIsInstanceCallLabel, DebugEnabled); + + XS.Label(xAfterIsInstanceCallLabel); + + XS.Pop(RAX); + XS.Compare(RAX, 0); + XS.Jump(ConditionalTestEnum.Equal, xReturnNullLabel); + XS.Jump(xNextPositionLabel); + + XS.Label(xReturnNullLabel); + + XS.Add(RSP, 8); + XS.Push(0); + XS.Push(0); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldarg.cs b/source/Cosmos.IL2CPU/IL/Ldarg.cs index 15e1f6ceb..3afff5c1e 100644 --- a/source/Cosmos.IL2CPU/IL/Ldarg.cs +++ b/source/Cosmos.IL2CPU/IL/Ldarg.cs @@ -1,197 +1,197 @@ -using Cosmos.IL2CPU.ILOpCodes; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldarg)] - public class Ldarg : ILOp - { - public Ldarg(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpVar = (OpVar)aOpCode; - DoExecute(Assembler, aMethod, xOpVar.Value); - } - - /// - /// This methods gives the full displacement for an argument. Arguments are in "reverse" order: - /// public static int Add(int a, int b) - /// In this situation, argument b is at EBP+8, argument A is at EBP+12 - /// - /// - /// After the method returns, the return value is on the stack. This means, that when the return size is larger than the - /// total argument size, we need to reserve extra stack: - /// public static Int64 Convert(int value) - /// In this situation, argument value is at EBP+12 - /// - /// - /// - /// - /// - public static int GetArgumentDisplacement(Il2cpuMethodInfo aMethod, ushort aIndex) - { - var xMethodBase = aMethod.MethodBase; - if (aMethod.PluggedMethod != null) - { - xMethodBase = aMethod.PluggedMethod.MethodBase; - } - var xMethodInfo = xMethodBase as MethodInfo; - var xDeclaringType = xMethodBase.DeclaringType; - - Type xReturnType = null; - if (xMethodInfo != null) - { - xReturnType = xMethodInfo.ReturnType; - } - - bool xIsStatic = aMethod.MethodBase.IsStatic; - var xParameterTypes = xMethodBase.GetParameters().Select(p => p.ParameterType).ToArray(); - - return GetArgumentDisplacement(aIndex, xDeclaringType, xParameterTypes, xReturnType, xIsStatic); - } - - public static int GetArgumentDisplacement(ushort aIndex, Type aDeclaringType, Type[] aParameterTypes, Type aReturnType, bool aIsStatic) - { - uint xReturnSize = 0; - if (aReturnType != null) - { - xReturnSize = Align(SizeOfType(aReturnType), 4); - } - - uint xOffset = 8; - var xCorrectedOpValValue = aIndex; - if (!aIsStatic && aIndex > 0) - { - // if the method has a $this, the OpCode value includes the this at index 0, but GetParameters() doesnt include the this - xCorrectedOpValValue -= 1; - } - var xParams = aParameterTypes; - - uint xArgSize = 0; - foreach (var xParam in xParams) - { - xArgSize += Align(SizeOfType(xParam), 4); - } - if (!aIsStatic) - { - // Add $this pointer - if (aDeclaringType.IsValueType) - { - // value types get a reference passed to the actual value, so pointer: - xArgSize += 4; - } - else - { - xArgSize += Align(SizeOfType(aDeclaringType), 4); - } - } - - uint xCurArgSize; - if (aIndex == 0 && !aIsStatic) - { - // return the this parameter, which is not in .GetParameters() - if (aDeclaringType.IsValueType) - { - // value types get a reference passed to the actual value, so pointer: - xCurArgSize = 4; - } - else - { - xCurArgSize = Align(SizeOfType(aDeclaringType), 4); - } - - for (int i = xParams.Length - 1; i >= aIndex; i--) - { - var xSize = Align(SizeOfType(xParams[i]), 4); - xOffset += xSize; - } - - } - else - { - xCurArgSize = Align(SizeOfType(xParams[xCorrectedOpValValue]), 4); - - for (int i = xParams.Length - 1; i > xCorrectedOpValValue; i--) - { - var xSize = Align(SizeOfType(xParams[i]), 4); - xOffset += xSize; - } - } - if (xReturnSize > xArgSize) - { - uint xExtraSize = xReturnSize - xArgSize; - xOffset += xExtraSize; - } - - return (int)(xOffset + xCurArgSize - 4); - - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, ushort aParam) - { - var xDisplacement = GetArgumentDisplacement(aMethod, aParam); - var xType = GetArgumentType(aMethod, aParam); - uint xArgRealSize = SizeOfType(xType); - uint xArgSize = Align(xArgRealSize, 4); - - XS.Comment("Arg idx = " + aParam); - XS.Comment("Arg type = " + xType); - XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); - if (IsIntegerBasedType(xType) && xArgRealSize == 1 || xArgRealSize == 2) - { - if (TypeIsSigned(xType)) - { - XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize)); - } - else - { - XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize)); - } - - XS.Push(EAX); - } - else - { - for (int i = 0; i < xArgSize / 4; i++) - { - XS.Push(EBP, isIndirect: true, displacement: xDisplacement - i * 4); - } - } - } - - public static Type GetArgumentType(Il2cpuMethodInfo aMethod, ushort aParam) - { - Type xArgType; - if (aMethod.MethodBase.IsStatic) - { - xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; - } - else - { - if (aParam == 0u) - { - xArgType = aMethod.MethodBase.DeclaringType; - if (xArgType.IsValueType) - { - xArgType = xArgType.MakeByRefType(); - } - } - else - { - xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; - } - } - - return xArgType; - } - } -} +using Cosmos.IL2CPU.ILOpCodes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldarg)] + public class Ldarg : ILOp + { + public Ldarg(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpVar = (OpVar)aOpCode; + DoExecute(Assembler, aMethod, xOpVar.Value); + } + + /// + /// This methods gives the full displacement for an argument. Arguments are in "reverse" order: + /// public static int Add(int a, int b) + /// In this situation, argument b is at EBP+8, argument A is at EBP+12 + /// + /// + /// After the method returns, the return value is on the stack. This means, that when the return size is larger than the + /// total argument size, we need to reserve extra stack: + /// public static Int64 Convert(int value) + /// In this situation, argument value is at EBP+12 + /// + /// + /// + /// + /// + public static int GetArgumentDisplacement(Il2cpuMethodInfo aMethod, ushort aIndex) + { + var xMethodBase = aMethod.MethodBase; + if (aMethod.PluggedMethod != null) + { + xMethodBase = aMethod.PluggedMethod.MethodBase; + } + var xMethodInfo = xMethodBase as MethodInfo; + var xDeclaringType = xMethodBase.DeclaringType; + + Type xReturnType = null; + if (xMethodInfo != null) + { + xReturnType = xMethodInfo.ReturnType; + } + + bool xIsStatic = aMethod.MethodBase.IsStatic; + var xParameterTypes = xMethodBase.GetParameters().Select(p => p.ParameterType).ToArray(); + + return GetArgumentDisplacement(aIndex, xDeclaringType, xParameterTypes, xReturnType, xIsStatic); + } + + public static int GetArgumentDisplacement(ushort aIndex, Type aDeclaringType, Type[] aParameterTypes, Type aReturnType, bool aIsStatic) + { + uint xReturnSize = 0; + if (aReturnType != null) + { + xReturnSize = Align(SizeOfType(aReturnType), 4); + } + + uint xOffset = 8; + var xCorrectedOpValValue = aIndex; + if (!aIsStatic && aIndex > 0) + { + // if the method has a $this, the OpCode value includes the this at index 0, but GetParameters() doesnt include the this + xCorrectedOpValValue -= 1; + } + var xParams = aParameterTypes; + + uint xArgSize = 0; + foreach (var xParam in xParams) + { + xArgSize += Align(SizeOfType(xParam), 4); + } + if (!aIsStatic) + { + // Add $this pointer + if (aDeclaringType.IsValueType) + { + // value types get a reference passed to the actual value, so pointer: + xArgSize += 4; + } + else + { + xArgSize += Align(SizeOfType(aDeclaringType), 4); + } + } + + uint xCurArgSize; + if (aIndex == 0 && !aIsStatic) + { + // return the this parameter, which is not in .GetParameters() + if (aDeclaringType.IsValueType) + { + // value types get a reference passed to the actual value, so pointer: + xCurArgSize = 4; + } + else + { + xCurArgSize = Align(SizeOfType(aDeclaringType), 4); + } + + for (int i = xParams.Length - 1; i >= aIndex; i--) + { + var xSize = Align(SizeOfType(xParams[i]), 4); + xOffset += xSize; + } + + } + else + { + xCurArgSize = Align(SizeOfType(xParams[xCorrectedOpValValue]), 4); + + for (int i = xParams.Length - 1; i > xCorrectedOpValValue; i--) + { + var xSize = Align(SizeOfType(xParams[i]), 4); + xOffset += xSize; + } + } + if (xReturnSize > xArgSize) + { + uint xExtraSize = xReturnSize - xArgSize; + xOffset += xExtraSize; + } + + return (int)(xOffset + xCurArgSize - 4); + + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, ushort aParam) + { + var xDisplacement = GetArgumentDisplacement(aMethod, aParam); + var xType = GetArgumentType(aMethod, aParam); + uint xArgRealSize = SizeOfType(xType); + uint xArgSize = Align(xArgRealSize, 4); + + XS.Comment("Arg idx = " + aParam); + XS.Comment("Arg type = " + xType); + XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); + if (IsIntegerBasedType(xType) && xArgRealSize == 1 || xArgRealSize == 2) + { + if (TypeIsSigned(xType)) + { + XS.MoveSignExtend(RAX, RBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize)); + } + else + { + XS.MoveZeroExtend(RAX, RBP, sourceIsIndirect: true, sourceDisplacement: xDisplacement, size: (RegisterSize)(8 * xArgRealSize)); + } + + XS.Push(RAX); + } + else + { + for (int i = 0; i < xArgSize / 4; i++) + { + XS.Push(RBP, isIndirect: true, displacement: xDisplacement - i * 4); + } + } + } + + public static Type GetArgumentType(Il2cpuMethodInfo aMethod, ushort aParam) + { + Type xArgType; + if (aMethod.MethodBase.IsStatic) + { + xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; + } + else + { + if (aParam == 0u) + { + xArgType = aMethod.MethodBase.DeclaringType; + if (xArgType.IsValueType) + { + xArgType = xArgType.MakeByRefType(); + } + } + else + { + xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; + } + } + + return xArgType; + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldarga.cs b/source/Cosmos.IL2CPU/IL/Ldarga.cs index b7e7b4f7f..5222bdf96 100644 --- a/source/Cosmos.IL2CPU/IL/Ldarga.cs +++ b/source/Cosmos.IL2CPU/IL/Ldarga.cs @@ -1,67 +1,67 @@ -using Cosmos.IL2CPU.ILOpCodes; -using System; -using XSharp; -using static XSharp.XSRegisters; - - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldarga)] - public class Ldarga : ILOp - { - public Ldarga(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpVar = (OpVar)aOpCode; - DoExecute(Assembler, aMethod, xOpVar.Value); - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, ushort aParam) - { - var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, aParam); - - /* - * The function GetArgumentDisplacement() does not give the correct displacement for the Ldarga opcode - * we need to "fix" it subtracting the argSize and 4 - */ - Type xArgType; - if (aMethod.MethodBase.IsStatic) - { - xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; - } - else - { - if (aParam == 0u) - { - xArgType = aMethod.MethodBase.DeclaringType; - if (xArgType.IsValueType) - { - xArgType = xArgType.MakeByRefType(); - } - } - else - { - xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; - } - } - - uint xArgRealSize = SizeOfType(xArgType); - uint xArgSize = Align(xArgRealSize, 4); - XS.Comment("Arg idx = " + aParam); - XS.Comment("Arg type = " + xArgType); - XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); - - xDisplacement -= (int)(xArgSize - 4); - XS.Comment("Real displacement " + xDisplacement); - - XS.Set(EAX, EBP); - XS.Set(EBX, (uint)xDisplacement); - XS.Add(EAX, EBX); - XS.Push(EAX); - } - } -} +using Cosmos.IL2CPU.ILOpCodes; +using System; +using XSharp; +using static XSharp.XSRegisters; + + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldarga)] + public class Ldarga : ILOp + { + public Ldarga(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpVar = (OpVar)aOpCode; + DoExecute(Assembler, aMethod, xOpVar.Value); + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, ushort aParam) + { + var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, aParam); + + /* + * The function GetArgumentDisplacement() does not give the correct displacement for the Ldarga opcode + * we need to "fix" it subtracting the argSize and 4 + */ + Type xArgType; + if (aMethod.MethodBase.IsStatic) + { + xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; + } + else + { + if (aParam == 0u) + { + xArgType = aMethod.MethodBase.DeclaringType; + if (xArgType.IsValueType) + { + xArgType = xArgType.MakeByRefType(); + } + } + else + { + xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; + } + } + + uint xArgRealSize = SizeOfType(xArgType); + uint xArgSize = Align(xArgRealSize, 4); + XS.Comment("Arg idx = " + aParam); + XS.Comment("Arg type = " + xArgType); + XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); + + xDisplacement -= (int)(xArgSize - 4); + XS.Comment("Real displacement " + xDisplacement); + + XS.Set(RAX, RBP); + XS.Set(RBX, (uint)xDisplacement); + XS.Add(RAX, RBX); + XS.Push(RAX); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs b/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs index 9a8ee94d3..97ffae3a3 100644 --- a/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs +++ b/source/Cosmos.IL2CPU/IL/Ldelem_Ref.cs @@ -1,117 +1,117 @@ -using System; - -using CPUx86 = XSharp.Assembler.x86; -using IL2CPU.API; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ldelem_Ref)] - public class Ldelem_Ref : ILOp - { - public Ldelem_Ref(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - Assemble(Assembler, 8, false, aMethod, aOpCode, DebugEnabled); - } - - public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) - { - // stack = index - // stack + 2 = array - DoNullReferenceCheck(aAssembler, debugEnabled, 8); - - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; - var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; - XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 - XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array - XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 - Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length - XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 - XS.Compare(EAX, EBX); - XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); - - XS.Compare(EBX, 0); - XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); - - XS.Label(xIndexOutOfRangeExeptionLabel); - XS.Pop(EAX); - XS.Pop(EAX); - Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); - - XS.Label(xNoIndexOutOfRangeExeptionLabel); - XS.Push(EBX); //_, array, 0 -> _, array, 0, index - - // calculate element offset into array memory (including header) - XS.Pop(EAX); - XS.Set(EDX, aElementSize); - XS.Multiply(EDX); - XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); - - if (aElementSize > 4) - { - // we start copying the last bytes - XS.Add(EAX, aElementSize - 4); - } - - // pop the array now - XS.Add(ESP, 4); - XS.Pop(EDX); - - XS.Add(EDX, EAX); - - var xSizeLeft = aElementSize; - while (xSizeLeft > 0) - { - var xCurrentStep = Math.Min(xSizeLeft, 4); - if (xSizeLeft % 4 != 0) - { - xCurrentStep = xSizeLeft % 4; - } - - xSizeLeft = xSizeLeft - xCurrentStep; - switch (xCurrentStep) - { - case 1: - if (isSigned) - { - XS.MoveSignExtend(ECX,EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); - } - else - { - XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Byte8); - } - XS.Push(ECX); - break; - case 2: - if (isSigned) - { - XS.MoveSignExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); - } - else - { - XS.MoveZeroExtend(ECX, EDX, sourceIsIndirect: true, size: RegisterSize.Short16); - } - XS.Push(ECX); - break; - case 4: - // copy a full dword - XS.Push(EDX, true); - XS.Sub(EDX, 4); // move to previous 4 bytes - break; - //case 8: - // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true}; - // XS.Push(XSRegisters.EDX, isIndirect: true); - // break; - } - } - } - } -} +using System; + +using CPUx86 = XSharp.Assembler.x86; +using IL2CPU.API; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ldelem_Ref)] + public class Ldelem_Ref : ILOp + { + public Ldelem_Ref(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + Assemble(Assembler, 8, false, aMethod, aOpCode, DebugEnabled); + } + + public static void Assemble(Assembler aAssembler, uint aElementSize, bool isSigned, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) + { + // stack = index + // stack + 2 = array + DoNullReferenceCheck(aAssembler, debugEnabled, 8); + + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; + var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; + XS.Pop(RBX); //get Position _, array, 0, index -> _, array, 0 + XS.Push(RSP, true, 4); // _, array, 0 => _, array, 0, array + XS.Push(RSP, true, 12); // _, array, 0, array => _, array, 0, array, 0 + Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length + XS.Pop(RAX); //Length of array _, array, 0, length -> _, array, 0 + XS.Compare(RAX, RBX); + XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); + + XS.Compare(RBX, 0); + XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); + + XS.Label(xIndexOutOfRangeExeptionLabel); + XS.Pop(RAX); + XS.Pop(RAX); + Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); + + XS.Label(xNoIndexOutOfRangeExeptionLabel); + XS.Push(RBX); //_, array, 0 -> _, array, 0, index + + // calculate element offset into array memory (including header) + XS.Pop(RAX); + XS.Set(RDX, aElementSize); + XS.Multiply(RDX); + XS.Add(RAX, ObjectUtils.FieldDataOffset + 4); + + if (aElementSize > 4) + { + // we start copying the last bytes + XS.Add(RAX, aElementSize - 4); + } + + // pop the array now + XS.Add(RSP, 4); + XS.Pop(RDX); + + XS.Add(RDX, RAX); + + var xSizeLeft = aElementSize; + while (xSizeLeft > 0) + { + var xCurrentStep = Math.Min(xSizeLeft, 4); + if (xSizeLeft % 4 != 0) + { + xCurrentStep = xSizeLeft % 4; + } + + xSizeLeft = xSizeLeft - xCurrentStep; + switch (xCurrentStep) + { + case 1: + if (isSigned) + { + XS.MoveSignExtend(RCX,RDX, sourceIsIndirect: true, size: RegisterSize.Byte8); + } + else + { + XS.MoveZeroExtend(RCX, RDX, sourceIsIndirect: true, size: RegisterSize.Byte8); + } + XS.Push(RCX); + break; + case 2: + if (isSigned) + { + XS.MoveSignExtend(RCX, RDX, sourceIsIndirect: true, size: RegisterSize.Short16); + } + else + { + XS.MoveZeroExtend(RCX, RDX, sourceIsIndirect: true, size: RegisterSize.Short16); + } + XS.Push(RCX); + break; + case 4: + // copy a full dword + XS.Push(RDX, true); + XS.Sub(RDX, 4); // move to previous 4 bytes + break; + //case 8: + // new CPUx86.Push {DestinationReg = CPUx86.Registers.EDX, DestinationDisplacement = 4, DestinationIsIndirect = true}; + // XS.Push(XSRegisters.EDX, isIndirect: true); + // break; + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldelema.cs b/source/Cosmos.IL2CPU/IL/Ldelema.cs index 849acd734..2a6656fc2 100644 --- a/source/Cosmos.IL2CPU/IL/Ldelema.cs +++ b/source/Cosmos.IL2CPU/IL/Ldelema.cs @@ -1,71 +1,71 @@ -using System.Linq; -using CPUx86 = XSharp.Assembler.x86; - -using Cosmos.IL2CPU.ILOpCodes; -using IL2CPU.API; -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldelema)] - public class Ldelema : ILOp - { - public Ldelema(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); - XS.Comment("Size: " + aElementSize); - - DoNullReferenceCheck(aAssembler, debugEnabled, 8); - - //Do check for index out of range - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; - var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; - XS.Pop(EBX); //get Position _, array, 0, index -> _, array, 0 - XS.Push(ESP, true, 4); // _, array, 0 => _, array, 0, array - XS.Push(ESP, true, 12); // _, array, 0, array => _, array, 0, array, 0 - Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length - XS.Pop(EAX); //Length of array _, array, 0, length -> _, array, 0 - XS.Compare(EAX, EBX); - XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); - - // Check if EBX is negative - XS.Compare(EBX, 0); - XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); - - XS.Label(xIndexOutOfRangeExeptionLabel); - XS.Pop(EAX); - XS.Pop(EAX); - Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); - - XS.Label(xNoIndexOutOfRangeExeptionLabel); - XS.Push(EBX); //_, array, 0 -> _, array, 0, index - - // calculate element offset into array memory (including header) - XS.Pop(EAX); - XS.Set(EDX, aElementSize); - XS.Multiply(EDX); - XS.Add(EAX, (uint)(ObjectUtils.FieldDataOffset + 4)); - - // pop the array now - XS.Add(ESP, 4); - XS.Pop(EDX); - - XS.Add(EDX, EAX); - XS.Push(EDX); - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpType = (OpType)aOpCode; - var xSize = SizeOfType(xOpType.Value); - Assemble(Assembler, xOpType, xSize, DebugEnabled, aMethod, aOpCode); - } - } -} +using System.Linq; +using CPUx86 = XSharp.Assembler.x86; + +using Cosmos.IL2CPU.ILOpCodes; +using IL2CPU.API; +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldelema)] + public class Ldelema : ILOp + { + public Ldelema(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public static void Assemble(XSharp.Assembler.Assembler aAssembler, OpType aOpType, uint aElementSize, bool debugEnabled, Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + XS.Comment("Arraytype: " + aOpType.StackPopTypes.Last().FullName); + XS.Comment("Size: " + aElementSize); + + DoNullReferenceCheck(aAssembler, debugEnabled, 8); + + //Do check for index out of range + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; + var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; + XS.Pop(RBX); //get Position _, array, 0, index -> _, array, 0 + XS.Push(RSP, true, 4); // _, array, 0 => _, array, 0, array + XS.Push(RSP, true, 12); // _, array, 0, array => _, array, 0, array, 0 + Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, array, 0 -> _, array, 0, length + XS.Pop(RAX); //Length of array _, array, 0, length -> _, array, 0 + XS.Compare(RAX, RBX); + XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); + + // Check if EBX is negative + XS.Compare(RBX, 0); + XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); + + XS.Label(xIndexOutOfRangeExeptionLabel); + XS.Pop(RAX); + XS.Pop(RAX); + Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); + + XS.Label(xNoIndexOutOfRangeExeptionLabel); + XS.Push(RBX); //_, array, 0 -> _, array, 0, index + + // calculate element offset into array memory (including header) + XS.Pop(RAX); + XS.Set(RDX, aElementSize); + XS.Multiply(RDX); + XS.Add(RAX, (uint)(ObjectUtils.FieldDataOffset + 4)); + + // pop the array now + XS.Add(RSP, 4); + XS.Pop(RDX); + + XS.Add(RDX, RAX); + XS.Push(RDX); + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpType = (OpType)aOpCode; + var xSize = SizeOfType(xOpType.Value); + Assemble(Assembler, xOpType, xSize, DebugEnabled, aMethod, aOpCode); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldfld.cs b/source/Cosmos.IL2CPU/IL/Ldfld.cs index 290e3aeaa..010bd1ad2 100644 --- a/source/Cosmos.IL2CPU/IL/Ldfld.cs +++ b/source/Cosmos.IL2CPU/IL/Ldfld.cs @@ -1,203 +1,203 @@ -using System; - -using IL2CPU.API; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Finds the value of a field in the object whose reference is currently on the evaluation stack. - /// - /// - /// MSDN: - /// The stack transitional behavior, in sequential order, is: - /// 1. An object reference (or pointer) is pushed onto the stack. - /// 2. The object reference (or pointer) is popped from the stack; the value of the specified field in the object is found. - /// 3. The value stored in the field is pushed onto the stack. - /// The ldfld instruction pushes the value of a field located in an object onto the stack. - /// The object must be on the stack as an object reference (type O), a managed pointer (type &), - /// an unmanaged pointer (type native int), a transient pointer (type *), or an instance of a value type. - /// The use of an unmanaged pointer is not permitted in verifiable code. - /// The object's field is specified by a metadata token that must refer to a field member. - /// The return type is the same as the one associated with the field. The field may be either an instance field - /// (in which case the object must not be a null reference) or a static field. - /// - /// The ldfld instruction can be preceded by either or both of the Unaligned and Volatile prefixes. - /// - /// NullReferenceException is thrown if the object is null and the field is not static. - /// - /// MissingFieldException is thrown if the specified field is not found in the metadata. - /// - /// This is typically checked when Microsoft Intermediate Language (MSIL) instructions are converted to native code, not at run time. - /// - [OpCode(ILOpCode.Code.Ldfld)] - public class Ldfld : ILOp - { - public Ldfld(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpCode = (OpField)aOpCode; - var xStackType = aOpCode.StackPopTypes[0]; - - var xFieldInfo = ResolveField(xOpCode.Value); - var xDeclaringType = xFieldInfo.DeclaringType; - var xFieldType = xFieldInfo.FieldType; - var xOffset = GetFieldOffset(xFieldInfo); - - XS.Comment("Field: " + xFieldInfo.Id); - XS.Comment("Type: " + xFieldInfo.FieldType.ToString()); - XS.Comment("Size: " + xFieldInfo.Size); - XS.Comment("DeclaringType: " + xDeclaringType.FullName); - XS.Comment("TypeOnStack: " + xStackType.FullName); - XS.Comment("Offset: " + xOffset + " (includes object header)"); - - if (xDeclaringType.IsValueType && MemberInfoComparer.Instance.Equals(xDeclaringType, xStackType)) - { - var xDeclaringTypeStackSize = Align(SizeOfType(xDeclaringType), 4); - var xFieldSize = xFieldInfo.Size; - var xStackOffset = (int)(-xDeclaringTypeStackSize + xOffset + xFieldSize - 4); - - XS.Add(ESP, xDeclaringTypeStackSize); - - if ((xFieldInfo.Size < 4 && IsIntegerBasedType(xFieldType)) - || xFieldType == typeof(bool) - || xFieldType == typeof(char)) - { - if (TypeIsSigned(xFieldType)) - { - XS.MoveSignExtend(EAX, ESP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize)); - XS.Push(EAX); - } - else - { - XS.MoveZeroExtend(EAX, ESP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize)); - XS.Push(EAX); - } - - return; - } - - for (int i = 0; i < xFieldSize / 4; i++) - { - XS.Push(ESP, displacement: xStackOffset); - } - - switch (xFieldSize % 4) - { - case 0: - break; - case 1: - XS.Xor(EAX, EAX); - XS.Set(AL, ESP, sourceDisplacement: xStackOffset + 3); - XS.Push(EAX); - break; - case 2: - XS.Xor(EAX, EAX); - XS.Set(AX, ESP, sourceDisplacement: xStackOffset + 2); - XS.Push(EAX); - break; - case 3: - XS.Xor(EAX, EAX); - XS.Set(AX, ESP, sourceDisplacement: xStackOffset + 2); - XS.ShiftLeft(EAX, 4); - XS.Set(AL, ESP, sourceDisplacement: xStackOffset + 1); - XS.Push(EAX); - break; - default: - throw new NotImplementedException(); - } - - return; - } - - // pushed size is always 4 or 8 - var xSize = xFieldInfo.Size; - if (IsReferenceType(xStackType)) - { - DoNullReferenceCheck(Assembler, DebugEnabled, 4); - XS.Add(ESP, 4); - } - else - { - DoNullReferenceCheck(Assembler, DebugEnabled, 0); - } - XS.Pop(ECX); - - XS.Add(ECX, (uint)xOffset); - - if (xFieldInfo.IsExternalValue) - { - XS.Set(ECX, ECX, sourceIsIndirect: true); - } - - for (int i = 1; i <= xSize / 4; i++) - { - XS.Set(EAX, ECX, sourceDisplacement: (int)(xSize - i * 4)); - XS.Push(EAX); - } - - if(xSize % 4 != 0) - { - XS.Set(EAX, 0); - } - - switch (xSize % 4) - { - case 1: - XS.Set(AL, ECX, sourceIsIndirect: true); - XS.Push(EAX); - break; - - case 2: - XS.Set(AX, ECX, sourceIsIndirect: true); - XS.Push(EAX); - break; - - case 3: //For Release - XS.Set(EAX, ECX, sourceIsIndirect: true); - XS.ShiftRight(EAX, 8); - XS.Push(EAX); - break; - - case 0: - { - break; - } - default: - throw new Exception(string.Format("Remainder size {0} {1:D} not supported!", xFieldInfo.FieldType.ToString(), xSize)); - } - } - - public static int GetFieldOffset(Type aDeclaringType, string aFieldId) - { - int xExtraOffset = 0; - var xFieldInfo = ResolveField(aDeclaringType, aFieldId, true); - bool xNeedsGC = IsReferenceType(aDeclaringType); - if (xNeedsGC) - { - xExtraOffset = 12; - } - return (int)(xExtraOffset + xFieldInfo.Offset); - } - - public static int GetFieldOffset(_FieldInfo fieldInfo) - { - var offset = (int)fieldInfo.Offset; - - if (IsReferenceType(fieldInfo.DeclaringType)) - { - offset += ObjectUtils.FieldDataOffset; - } - - return offset; - } - } -} +using System; + +using IL2CPU.API; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Finds the value of a field in the object whose reference is currently on the evaluation stack. + /// + /// + /// MSDN: + /// The stack transitional behavior, in sequential order, is: + /// 1. An object reference (or pointer) is pushed onto the stack. + /// 2. The object reference (or pointer) is popped from the stack; the value of the specified field in the object is found. + /// 3. The value stored in the field is pushed onto the stack. + /// The ldfld instruction pushes the value of a field located in an object onto the stack. + /// The object must be on the stack as an object reference (type O), a managed pointer (type &), + /// an unmanaged pointer (type native int), a transient pointer (type *), or an instance of a value type. + /// The use of an unmanaged pointer is not permitted in verifiable code. + /// The object's field is specified by a metadata token that must refer to a field member. + /// The return type is the same as the one associated with the field. The field may be either an instance field + /// (in which case the object must not be a null reference) or a static field. + /// + /// The ldfld instruction can be preceded by either or both of the Unaligned and Volatile prefixes. + /// + /// NullReferenceException is thrown if the object is null and the field is not static. + /// + /// MissingFieldException is thrown if the specified field is not found in the metadata. + /// + /// This is typically checked when Microsoft Intermediate Language (MSIL) instructions are converted to native code, not at run time. + /// + [OpCode(ILOpCode.Code.Ldfld)] + public class Ldfld : ILOp + { + public Ldfld(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpCode = (OpField)aOpCode; + var xStackType = aOpCode.StackPopTypes[0]; + + var xFieldInfo = ResolveField(xOpCode.Value); + var xDeclaringType = xFieldInfo.DeclaringType; + var xFieldType = xFieldInfo.FieldType; + var xOffset = GetFieldOffset(xFieldInfo); + + XS.Comment("Field: " + xFieldInfo.Id); + XS.Comment("Type: " + xFieldInfo.FieldType.ToString()); + XS.Comment("Size: " + xFieldInfo.Size); + XS.Comment("DeclaringType: " + xDeclaringType.FullName); + XS.Comment("TypeOnStack: " + xStackType.FullName); + XS.Comment("Offset: " + xOffset + " (includes object header)"); + + if (xDeclaringType.IsValueType && MemberInfoComparer.Instance.Equals(xDeclaringType, xStackType)) + { + var xDeclaringTypeStackSize = Align(SizeOfType(xDeclaringType), 4); + var xFieldSize = xFieldInfo.Size; + var xStackOffset = (int)(-xDeclaringTypeStackSize + xOffset + xFieldSize - 4); + + XS.Add(RSP, xDeclaringTypeStackSize); + + if ((xFieldInfo.Size < 4 && IsIntegerBasedType(xFieldType)) + || xFieldType == typeof(bool) + || xFieldType == typeof(char)) + { + if (TypeIsSigned(xFieldType)) + { + XS.MoveSignExtend(RAX, RSP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize)); + XS.Push(RAX); + } + else + { + XS.MoveZeroExtend(RAX, RSP, sourceDisplacement: xStackOffset + (4 - (int)xFieldSize), size: (RegisterSize)(8 * xFieldSize)); + XS.Push(RAX); + } + + return; + } + + for (int i = 0; i < xFieldSize / 4; i++) + { + XS.Push(RSP, displacement: xStackOffset); + } + + switch (xFieldSize % 4) + { + case 0: + break; + case 1: + XS.Xor(RAX, RAX); + XS.Set(AL, RSP, sourceDisplacement: xStackOffset + 3); + XS.Push(RAX); + break; + case 2: + XS.Xor(RAX, RAX); + XS.Set(AX, RSP, sourceDisplacement: xStackOffset + 2); + XS.Push(RAX); + break; + case 3: + XS.Xor(RAX, RAX); + XS.Set(AX, RSP, sourceDisplacement: xStackOffset + 2); + XS.ShiftLeft(RAX, 4); + XS.Set(AL, RSP, sourceDisplacement: xStackOffset + 1); + XS.Push(RAX); + break; + default: + throw new NotImplementedException(); + } + + return; + } + + // pushed size is always 4 or 8 + var xSize = xFieldInfo.Size; + if (IsReferenceType(xStackType)) + { + DoNullReferenceCheck(Assembler, DebugEnabled, 4); + XS.Add(RSP, 4); + } + else + { + DoNullReferenceCheck(Assembler, DebugEnabled, 0); + } + XS.Pop(RCX); + + XS.Add(RCX, (uint)xOffset); + + if (xFieldInfo.IsExternalValue) + { + XS.Set(RCX, RCX, sourceIsIndirect: true); + } + + for (int i = 1; i <= xSize / 4; i++) + { + XS.Set(RAX, RCX, sourceDisplacement: (int)(xSize - i * 4)); + XS.Push(RAX); + } + + if(xSize % 4 != 0) + { + XS.Set(RAX, 0); + } + + switch (xSize % 4) + { + case 1: + XS.Set(AL, RCX, sourceIsIndirect: true); + XS.Push(RAX); + break; + + case 2: + XS.Set(AX, RCX, sourceIsIndirect: true); + XS.Push(RAX); + break; + + case 3: //For Release + XS.Set(RAX, RCX, sourceIsIndirect: true); + XS.ShiftRight(RAX, 8); + XS.Push(RAX); + break; + + case 0: + { + break; + } + default: + throw new Exception(string.Format("Remainder size {0} {1:D} not supported!", xFieldInfo.FieldType.ToString(), xSize)); + } + } + + public static int GetFieldOffset(Type aDeclaringType, string aFieldId) + { + int xExtraOffset = 0; + var xFieldInfo = ResolveField(aDeclaringType, aFieldId, true); + bool xNeedsGC = IsReferenceType(aDeclaringType); + if (xNeedsGC) + { + xExtraOffset = 12; + } + return (int)(xExtraOffset + xFieldInfo.Offset); + } + + public static int GetFieldOffset(_FieldInfo fieldInfo) + { + var offset = (int)fieldInfo.Offset; + + if (IsReferenceType(fieldInfo.DeclaringType)) + { + offset += ObjectUtils.FieldDataOffset; + } + + return offset; + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldflda.cs b/source/Cosmos.IL2CPU/IL/Ldflda.cs index 2cdc7499a..561dcc3e7 100644 --- a/source/Cosmos.IL2CPU/IL/Ldflda.cs +++ b/source/Cosmos.IL2CPU/IL/Ldflda.cs @@ -1,70 +1,70 @@ -using System; -using Cosmos.IL2CPU.Extensions; -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldflda)] - public class Ldflda : ILOp - { - public Ldflda(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpCode = (ILOpCodes.OpField)aOpCode; - DoExecute(Assembler, aMethod, xOpCode.Value.DeclaringType, xOpCode.Value.GetFullName(), true, DebugEnabled, aOpCode.StackPopTypes[0]); - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, Type aDeclaringType, string aField, bool aDerefValue, bool aDebugEnabled, Type aTypeOnStack) - { - var xFieldInfo = ResolveField(aDeclaringType, aField, true); - DoExecute(Assembler, aMethod, aDeclaringType, xFieldInfo, aDerefValue, aDebugEnabled, aTypeOnStack); - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, Type aDeclaringType, _FieldInfo aField, bool aDerefValue, bool aDebugEnabled, Type aTypeOnStack) - { - XS.Comment("Field: " + aField.Id); - int xExtraOffset = 0; - - bool xNeedsGC = aDeclaringType.IsClass && !aDeclaringType.IsValueType; - - if (xNeedsGC) - { - xExtraOffset = 12; - } - - if (!aTypeOnStack.IsPointer && aDeclaringType.IsClass) - { - DoNullReferenceCheck(Assembler, aDebugEnabled, 4); - XS.Add(ESP, 4); - } - else - { - DoNullReferenceCheck(Assembler, aDebugEnabled, 0); - } - - if (aDerefValue && aField.IsExternalValue) - { - XS.Set(ESP, EAX, destinationIsIndirect: true); - } - else - { - XS.Pop(EAX); - if (aDeclaringType.Name == "RawArrayData" && aField.Field.Name == "Data") - { - // if we accidently load 64bit assemblies, we get an incorrect extra 4 bytes of offset, so we just hardcode the offset - XS.Add(EAX, (uint)(4 + xExtraOffset)); - } - else - { - XS.Add(EAX, (uint)(aField.Offset + xExtraOffset)); - } - XS.Push(EAX); - } - } - } -} +using System; +using Cosmos.IL2CPU.Extensions; +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldflda)] + public class Ldflda : ILOp + { + public Ldflda(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpCode = (ILOpCodes.OpField)aOpCode; + DoExecute(Assembler, aMethod, xOpCode.Value.DeclaringType, xOpCode.Value.GetFullName(), true, DebugEnabled, aOpCode.StackPopTypes[0]); + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, Type aDeclaringType, string aField, bool aDerefValue, bool aDebugEnabled, Type aTypeOnStack) + { + var xFieldInfo = ResolveField(aDeclaringType, aField, true); + DoExecute(Assembler, aMethod, aDeclaringType, xFieldInfo, aDerefValue, aDebugEnabled, aTypeOnStack); + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, Type aDeclaringType, _FieldInfo aField, bool aDerefValue, bool aDebugEnabled, Type aTypeOnStack) + { + XS.Comment("Field: " + aField.Id); + int xExtraOffset = 0; + + bool xNeedsGC = aDeclaringType.IsClass && !aDeclaringType.IsValueType; + + if (xNeedsGC) + { + xExtraOffset = 12; + } + + if (!aTypeOnStack.IsPointer && aDeclaringType.IsClass) + { + DoNullReferenceCheck(Assembler, aDebugEnabled, 4); + XS.Add(RSP, 4); + } + else + { + DoNullReferenceCheck(Assembler, aDebugEnabled, 0); + } + + if (aDerefValue && aField.IsExternalValue) + { + XS.Set(RSP, RAX, destinationIsIndirect: true); + } + else + { + XS.Pop(RAX); + if (aDeclaringType.Name == "RawArrayData" && aField.Field.Name == "Data") + { + // if we accidently load 64bit assemblies, we get an incorrect extra 4 bytes of offset, so we just hardcode the offset + XS.Add(RAX, (uint)(4 + xExtraOffset)); + } + else + { + XS.Add(RAX, (uint)(aField.Offset + xExtraOffset)); + } + XS.Push(RAX); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldind.cs b/source/Cosmos.IL2CPU/IL/Ldind.cs index bf0fdb5ae..5ff55d064 100644 --- a/source/Cosmos.IL2CPU/IL/Ldind.cs +++ b/source/Cosmos.IL2CPU/IL/Ldind.cs @@ -1,64 +1,64 @@ -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ldind_I)] - [OpCode(ILOpCode.Code.Ldind_I1)] - [OpCode(ILOpCode.Code.Ldind_I2)] - [OpCode(ILOpCode.Code.Ldind_I4)] - [OpCode(ILOpCode.Code.Ldind_I8)] - [OpCode(ILOpCode.Code.Ldind_U1)] - [OpCode(ILOpCode.Code.Ldind_U2)] - [OpCode(ILOpCode.Code.Ldind_U4)] - [OpCode(ILOpCode.Code.Ldind_R4)] - [OpCode(ILOpCode.Code.Ldind_R8)] - [OpCode(ILOpCode.Code.Ldind_Ref)] - public class Ldind : ILOp - { - public Ldind(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - DoNullReferenceCheck(Assembler, DebugEnabled, 0); - - XS.Pop(EAX); - - switch (aOpCode.OpCode) - { - case ILOpCode.Code.Ldind_I1: - XS.MoveSignExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8); - XS.Push(EAX); - break; - case ILOpCode.Code.Ldind_I2: - XS.MoveSignExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16); - XS.Push(EAX); - break; - case ILOpCode.Code.Ldind_U1: - XS.MoveZeroExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8); - XS.Push(EAX); - break; - case ILOpCode.Code.Ldind_U2: - XS.MoveZeroExtend(EAX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16); - XS.Push(EAX); - break; - case ILOpCode.Code.Ldind_I: - case ILOpCode.Code.Ldind_I4: - case ILOpCode.Code.Ldind_U4: - case ILOpCode.Code.Ldind_R4: - XS.Push(EAX, isIndirect: true); - break; - case ILOpCode.Code.Ldind_I8: - case ILOpCode.Code.Ldind_R8: - case ILOpCode.Code.Ldind_Ref: - XS.Push(EAX, displacement: 4); - XS.Push(EAX, isIndirect: true); - break; - } - } - } -} +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ldind_I)] + [OpCode(ILOpCode.Code.Ldind_I1)] + [OpCode(ILOpCode.Code.Ldind_I2)] + [OpCode(ILOpCode.Code.Ldind_I4)] + [OpCode(ILOpCode.Code.Ldind_I8)] + [OpCode(ILOpCode.Code.Ldind_U1)] + [OpCode(ILOpCode.Code.Ldind_U2)] + [OpCode(ILOpCode.Code.Ldind_U4)] + [OpCode(ILOpCode.Code.Ldind_R4)] + [OpCode(ILOpCode.Code.Ldind_R8)] + [OpCode(ILOpCode.Code.Ldind_Ref)] + public class Ldind : ILOp + { + public Ldind(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + DoNullReferenceCheck(Assembler, DebugEnabled, 0); + + XS.Pop(RAX); + + switch (aOpCode.OpCode) + { + case ILOpCode.Code.Ldind_I1: + XS.MoveSignExtend(RAX, RAX, sourceIsIndirect: true, size: RegisterSize.Byte8); + XS.Push(RAX); + break; + case ILOpCode.Code.Ldind_I2: + XS.MoveSignExtend(RAX, RAX, sourceIsIndirect: true, size: RegisterSize.Short16); + XS.Push(RAX); + break; + case ILOpCode.Code.Ldind_U1: + XS.MoveZeroExtend(RAX, RAX, sourceIsIndirect: true, size: RegisterSize.Byte8); + XS.Push(RAX); + break; + case ILOpCode.Code.Ldind_U2: + XS.MoveZeroExtend(RAX, RAX, sourceIsIndirect: true, size: RegisterSize.Short16); + XS.Push(RAX); + break; + case ILOpCode.Code.Ldind_I: + case ILOpCode.Code.Ldind_I4: + case ILOpCode.Code.Ldind_U4: + case ILOpCode.Code.Ldind_R4: + XS.Push(RAX, isIndirect: true); + break; + case ILOpCode.Code.Ldind_I8: + case ILOpCode.Code.Ldind_R8: + case ILOpCode.Code.Ldind_Ref: + XS.Push(RAX, displacement: 4); + XS.Push(RAX, isIndirect: true); + break; + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldlen.cs b/source/Cosmos.IL2CPU/IL/Ldlen.cs index 02efe5533..7682d9a5e 100644 --- a/source/Cosmos.IL2CPU/IL/Ldlen.cs +++ b/source/Cosmos.IL2CPU/IL/Ldlen.cs @@ -1,34 +1,34 @@ -using Cosmos.IL2CPU.ILOpCodes; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ldlen)] - public class Ldlen : ILOp - { - public Ldlen(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - Assemble(Assembler, DebugEnabled); - } - - public static void Assemble(Assembler aAssembler, bool debugEnabled, bool doNullReferenceCheck = true) - { - if (doNullReferenceCheck) - { - DoNullReferenceCheck(aAssembler, debugEnabled, 4); - } - - XS.Add(ESP, 4); - XS.Pop(EAX); - - XS.Push(EAX, displacement: 8); - } - } -} +using Cosmos.IL2CPU.ILOpCodes; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ldlen)] + public class Ldlen : ILOp + { + public Ldlen(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + Assemble(Assembler, DebugEnabled); + } + + public static void Assemble(Assembler aAssembler, bool debugEnabled, bool doNullReferenceCheck = true) + { + if (doNullReferenceCheck) + { + DoNullReferenceCheck(aAssembler, debugEnabled, 4); + } + + XS.Add(RSP, 4); + XS.Pop(RAX); + + XS.Push(RAX, displacement: 8); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldloc.cs b/source/Cosmos.IL2CPU/IL/Ldloc.cs index a20a02065..0c3de451b 100644 --- a/source/Cosmos.IL2CPU/IL/Ldloc.cs +++ b/source/Cosmos.IL2CPU/IL/Ldloc.cs @@ -1,66 +1,66 @@ -using Cosmos.IL2CPU.Extensions; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ldloc)] - public class Ldloc : ILOp - { - public Ldloc(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpVar = (OpVar)aOpCode; - var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; - var xStackCount = (int)GetStackCountForLocal(aMethod, xVar.LocalType); - var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); - var xSize = SizeOfType(xVar.LocalType); - bool xSigned = TypeIsSigned(xVar.LocalType); - - XS.Comment("Local type = " + xVar.LocalType); - XS.Comment("Local EBP offset = " + xEBPOffset); - XS.Comment("Local size = " + xSize); - - switch (xSize) - { - case 1: - if (xSigned) - { - XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Byte8); - } - else - { - XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Byte8); - } - XS.Push(EAX); - break; - case 2: - if (xSigned) - { - XS.MoveSignExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Short16); - } - else - { - XS.MoveZeroExtend(EAX, EBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Short16); - } - XS.Push(EAX); - break; - default: - for (int i = 0; i < xStackCount; i++) - { - //XS.Set(EAX, EBP, sourceDisplacement: 0 - (xEBPOffset + (i * 4))); - XS.Push(EBP, displacement: 0 - (xEBPOffset + i * 4)); - } - break; - } - } - } -} +using Cosmos.IL2CPU.Extensions; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ldloc)] + public class Ldloc : ILOp + { + public Ldloc(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpVar = (OpVar)aOpCode; + var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; + var xStackCount = (int)GetStackCountForLocal(aMethod, xVar.LocalType); + var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); + var xSize = SizeOfType(xVar.LocalType); + bool xSigned = TypeIsSigned(xVar.LocalType); + + XS.Comment("Local type = " + xVar.LocalType); + XS.Comment("Local EBP offset = " + xEBPOffset); + XS.Comment("Local size = " + xSize); + + switch (xSize) + { + case 1: + if (xSigned) + { + XS.MoveSignExtend(RAX, RBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Byte8); + } + else + { + XS.MoveZeroExtend(RAX, RBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Byte8); + } + XS.Push(RAX); + break; + case 2: + if (xSigned) + { + XS.MoveSignExtend(RAX, RBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Short16); + } + else + { + XS.MoveZeroExtend(RAX, RBP, sourceIsIndirect: true, sourceDisplacement: 0 - xEBPOffset, size: RegisterSize.Short16); + } + XS.Push(RAX); + break; + default: + for (int i = 0; i < xStackCount; i++) + { + //XS.Set(EAX, EBP, sourceDisplacement: 0 - (xEBPOffset + (i * 4))); + XS.Push(RBP, displacement: 0 - (xEBPOffset + i * 4)); + } + break; + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldloca.cs b/source/Cosmos.IL2CPU/IL/Ldloca.cs index fa2ff50f5..a0b58c6a6 100644 --- a/source/Cosmos.IL2CPU/IL/Ldloca.cs +++ b/source/Cosmos.IL2CPU/IL/Ldloca.cs @@ -1,33 +1,33 @@ -using Cosmos.IL2CPU.Extensions; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ldloca)] - public class Ldloca : ILOp - { - public Ldloca(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpVar = (OpVar)aOpCode; - var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; - var xEBPOffset = GetEBPOffsetForLocal(aMethod, xOpVar.Value); - xEBPOffset += (uint)(((int)GetStackCountForLocal(aMethod, xVar.LocalType) - 1) * 4); - - XS.Comment("Local type = " + xVar.LocalType); - XS.Comment("Local EBP offset = " + xEBPOffset); - - XS.Set(EAX, EBP); - XS.Sub(EAX, xEBPOffset); - XS.Push(EAX); - } - } -} +using Cosmos.IL2CPU.Extensions; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ldloca)] + public class Ldloca : ILOp + { + public Ldloca(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpVar = (OpVar)aOpCode; + var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; + var xEBPOffset = GetEBPOffsetForLocal(aMethod, xOpVar.Value); + xEBPOffset += (uint)(((int)GetStackCountForLocal(aMethod, xVar.LocalType) - 1) * 4); + + XS.Comment("Local type = " + xVar.LocalType); + XS.Comment("Local EBP offset = " + xEBPOffset); + + XS.Set(RAX, RBP); + XS.Sub(RAX, xEBPOffset); + XS.Push(RAX); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldobj.cs b/source/Cosmos.IL2CPU/IL/Ldobj.cs index b0ee20f83..314689c4c 100644 --- a/source/Cosmos.IL2CPU/IL/Ldobj.cs +++ b/source/Cosmos.IL2CPU/IL/Ldobj.cs @@ -1,90 +1,90 @@ -using System; - -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Ldobj)] - public class Ldobj : ILOp - { - public Ldobj(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - DoNullReferenceCheck(Assembler, DebugEnabled, 0); - OpType xType = (OpType)aOpCode; - DoAssemble(xType.Value); - } - - public static void DoAssemble(Type type) - { - if (type == null) - { - throw new ArgumentNullException(nameof(type)); - } - XS.Pop(EAX); - var xObjSize = SizeOfType(type); - - if (xObjSize < 4 && TypeIsSigned(type)) - { - if (xObjSize == 1) - { - XS.MoveSignExtend(EBX, EAX, sourceIsIndirect: true, size: RegisterSize.Byte8); - } - else if (xObjSize == 2) - { - XS.MoveSignExtend(EBX, EAX, sourceIsIndirect: true, size: RegisterSize.Short16); - } - XS.Push(EBX); - return; - } - - switch (xObjSize % 4) - { - case 1: - { - XS.Xor(EBX, EBX); - XS.Set(BL, EAX, sourceDisplacement: (int)(xObjSize - 1)); - //XS.ShiftLeft(XSRegisters.EBX, 24); - XS.Push(EBX); - break; - } - case 2: - { - XS.Xor(EBX, EBX); - XS.Set(BX, EAX, sourceDisplacement: (int)(xObjSize - 2)); - //XS.ShiftLeft(XSRegisters.EBX, 16); - XS.Push(EBX); - break; - } - case 3: - { - XS.Set(EBX, EAX, sourceDisplacement: (int)(xObjSize - 3)); - XS.And(EBX, 0xFFFFFF); - XS.Push(EBX); - break; - } - case 0: - { - break; - } - default: - throw new Exception("Remainder not supported!"); - } - - xObjSize -= xObjSize % 4; - - for (int i = 1; i <= xObjSize / 4; i++) - { - XS.Push(EAX, displacement: (int)(xObjSize - i * 4)); - } - } - } -} +using System; + +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Ldobj)] + public class Ldobj : ILOp + { + public Ldobj(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + DoNullReferenceCheck(Assembler, DebugEnabled, 0); + OpType xType = (OpType)aOpCode; + DoAssemble(xType.Value); + } + + public static void DoAssemble(Type type) + { + if (type == null) + { + throw new ArgumentNullException(nameof(type)); + } + XS.Pop(RAX); + var xObjSize = SizeOfType(type); + + if (xObjSize < 4 && TypeIsSigned(type)) + { + if (xObjSize == 1) + { + XS.MoveSignExtend(RBX, RAX, sourceIsIndirect: true, size: RegisterSize.Byte8); + } + else if (xObjSize == 2) + { + XS.MoveSignExtend(RBX, RAX, sourceIsIndirect: true, size: RegisterSize.Short16); + } + XS.Push(RBX); + return; + } + + switch (xObjSize % 4) + { + case 1: + { + XS.Xor(RBX, RBX); + XS.Set(BL, RAX, sourceDisplacement: (int)(xObjSize - 1)); + //XS.ShiftLeft(XSRegisters.EBX, 24); + XS.Push(RBX); + break; + } + case 2: + { + XS.Xor(RBX, RBX); + XS.Set(BX, RAX, sourceDisplacement: (int)(xObjSize - 2)); + //XS.ShiftLeft(XSRegisters.EBX, 16); + XS.Push(RBX); + break; + } + case 3: + { + XS.Set(RBX, RAX, sourceDisplacement: (int)(xObjSize - 3)); + XS.And(RBX, 0xFFFFFF); + XS.Push(RBX); + break; + } + case 0: + { + break; + } + default: + throw new Exception("Remainder not supported!"); + } + + xObjSize -= xObjSize % 4; + + for (int i = 1; i <= xObjSize / 4; i++) + { + XS.Push(RAX, displacement: (int)(xObjSize - i * 4)); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Ldsfld.cs b/source/Cosmos.IL2CPU/IL/Ldsfld.cs index 62eaf499c..4c8ab1e37 100644 --- a/source/Cosmos.IL2CPU/IL/Ldsfld.cs +++ b/source/Cosmos.IL2CPU/IL/Ldsfld.cs @@ -1,122 +1,122 @@ -using System; -using System.Linq; -using System.Reflection; - -using IL2CPU.API; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler; -using CPUx86 = XSharp.Assembler.x86; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldsfld)] - public class Ldsfld : ILOp - { - public Ldsfld(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - - var xType = aMethod.MethodBase.DeclaringType; - var xOpCode = (OpField)aOpCode; - FieldInfo xField = xOpCode.Value; - - // call cctor: - var xCctor = xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic).SingleOrDefault(); - if (xCctor != null) - { - XS.Call(LabelName.Get(xCctor)); - ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck"); - XS.Label(".AfterCCTorExceptionCheck"); - } - - //Assembler.Stack.Pop(); - //int aExtraOffset;// = 0; - //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType; - var xSize = SizeOfType(xField.FieldType); - //if( xNeedsGC ) - //{ - // aExtraOffset = 12; - //} - - string xDataName = LabelName.GetStaticFieldName(xField); - - var xTypeNeedsGC = IsReferenceType(xField.FieldType); - if (xTypeNeedsGC) - { - XS.Push(xDataName, isIndirect: true, displacement: 4); - XS.Push(0); - return; - } - - - if (xSize >= 4) - { - for (int i = 1; i <= xSize / 4; i++) - { - // Pop("eax"); - // Move(Assembler, "dword [" + mDataName + " + 0x" + (i * 4).ToString("X") + "]", "eax"); - new CPUx86.Push { DestinationRef = XSharp.Assembler.ElementReference.New(xDataName), DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize - i * 4) }; - } - switch (xSize % 4) - { - case 1: - { - XS.Set(XSRegisters.EAX, 0); - XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true); - XS.Push(XSRegisters.EAX); - break; - } - case 2: - { - XS.Set(XSRegisters.EAX, 0); - XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true); - XS.Push(XSRegisters.EAX); - break; - } - case 0: - { - break; - } - default: - //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); - throw new NotImplementedException(); - //break; - } - } - else - { - switch (xSize) - { - case 1: - { - XS.Set(XSRegisters.EAX, 0); - XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true); - XS.Push(XSRegisters.EAX); - break; - } - case 2: - { - XS.Set(XSRegisters.EAX, 0); - XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true); - XS.Push(XSRegisters.EAX); - break; - } - case 0: - { - break; - } - default: - //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); - throw new NotImplementedException(); - //break; - } - } - } - } -} +using System; +using System.Linq; +using System.Reflection; + +using IL2CPU.API; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler; +using CPUx86 = XSharp.Assembler.x86; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Ldsfld)] + public class Ldsfld : ILOp + { + public Ldsfld(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + + var xType = aMethod.MethodBase.DeclaringType; + var xOpCode = (OpField)aOpCode; + FieldInfo xField = xOpCode.Value; + + // call cctor: + var xCctor = xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic).SingleOrDefault(); + if (xCctor != null) + { + XS.Call(LabelName.Get(xCctor)); + ILOp.EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck"); + XS.Label(".AfterCCTorExceptionCheck"); + } + + //Assembler.Stack.Pop(); + //int aExtraOffset;// = 0; + //bool xNeedsGC = xField.FieldType.IsClass && !xField.FieldType.IsValueType; + var xSize = SizeOfType(xField.FieldType); + //if( xNeedsGC ) + //{ + // aExtraOffset = 12; + //} + + string xDataName = LabelName.GetStaticFieldName(xField); + + var xTypeNeedsGC = IsReferenceType(xField.FieldType); + if (xTypeNeedsGC) + { + XS.Push(xDataName, isIndirect: true, displacement: 4); + XS.Push(0); + return; + } + + + if (xSize >= 4) + { + for (int i = 1; i <= xSize / 4; i++) + { + // Pop("eax"); + // Move(Assembler, "dword [" + mDataName + " + 0x" + (i * 4).ToString("X") + "]", "eax"); + new CPUx86.Push { DestinationRef = XSharp.Assembler.ElementReference.New(xDataName), DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize - i * 4) }; + } + switch (xSize % 4) + { + case 1: + { + XS.Set(XSRegisters.RAX, 0); + XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true); + XS.Push(XSRegisters.RAX); + break; + } + case 2: + { + XS.Set(XSRegisters.RAX, 0); + XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true); + XS.Push(XSRegisters.RAX); + break; + } + case 0: + { + break; + } + default: + //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); + throw new NotImplementedException(); + //break; + } + } + else + { + switch (xSize) + { + case 1: + { + XS.Set(XSRegisters.RAX, 0); + XS.Set(XSRegisters.AL, xDataName, sourceIsIndirect: true); + XS.Push(XSRegisters.RAX); + break; + } + case 2: + { + XS.Set(XSRegisters.RAX, 0); + XS.Set(XSRegisters.AX, xDataName, sourceIsIndirect: true); + XS.Push(XSRegisters.RAX); + break; + } + case 0: + { + break; + } + default: + //EmitNotImplementedException( Assembler, GetServiceProvider(), "Ldsfld: Remainder size " + ( xSize % 4 ) + " not supported!", mCurLabel, mMethodInformation, mCurOffset, mNextLabel ); + throw new NotImplementedException(); + //break; + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Leave.cs b/source/Cosmos.IL2CPU/IL/Leave.cs index a3edabae0..d6e0a09db 100644 --- a/source/Cosmos.IL2CPU/IL/Leave.cs +++ b/source/Cosmos.IL2CPU/IL/Leave.cs @@ -1,35 +1,36 @@ -using System.Reflection.Metadata; -using Cosmos.IL2CPU.Extensions; -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Leave)] - public class Leave : ILOp - { - public Leave(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - string jumpTarget = AppAssembler.TmpBranchLabel(aMethod, aOpCode); - - // apparently, Roslyn changed something to the output. We now have to figure out where to jump to. - if (aOpCode.CurrentExceptionRegion.Kind.HasFlag(ExceptionRegionKind.Finally) - && aOpCode.CurrentExceptionRegion.HandlerOffset > aOpCode.Position) - { - string destination = $"{aMethod.MethodBase.GetFullName()}_LeaveAddress_{aOpCode.CurrentExceptionRegion.HandlerOffset:X2}"; - string source = AppAssembler.TmpBranchLabel(aMethod, aOpCode); - XS.Set(destination, source, destinationIsIndirect: true, size: RegisterSize.Int32); - XS.Jump(AppAssembler.TmpPosLabel(aMethod, aOpCode.CurrentExceptionRegion.HandlerOffset)); - } - else - { - XS.Jump(jumpTarget); - } - } - } -} +using System.Reflection.Metadata; +using Cosmos.IL2CPU.Extensions; +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Leave)] + public class Leave : ILOp + { + public Leave(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + string jumpTarget = AppAssembler.TmpBranchLabel(aMethod, aOpCode); + + // apparently, Roslyn changed something to the output. We now have to figure out where to jump to. + if (aOpCode.CurrentExceptionRegion.Kind.HasFlag(ExceptionRegionKind.Finally) + && aOpCode.CurrentExceptionRegion.HandlerOffset > aOpCode.Position) + { + string destination = $"{aMethod.MethodBase.GetFullName()}_LeaveAddress_{aOpCode.CurrentExceptionRegion.HandlerOffset:X2}"; + string source = AppAssembler.TmpBranchLabel(aMethod, aOpCode); + XS.Set(R10, source); //R10 contains source + XS.Set(destination, R10, destinationIsIndirect: true, size: RegisterSize.Long64); + XS.Jump(AppAssembler.TmpPosLabel(aMethod, aOpCode.CurrentExceptionRegion.HandlerOffset)); + } + else + { + XS.Jump(jumpTarget); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Mul.cs b/source/Cosmos.IL2CPU/IL/Mul.cs index 8030c59b9..0fcd4c036 100644 --- a/source/Cosmos.IL2CPU/IL/Mul.cs +++ b/source/Cosmos.IL2CPU/IL/Mul.cs @@ -1,125 +1,125 @@ -using System; -using XSharp.Assembler.x86.SSE; - -using XSharp; -using static XSharp.XSRegisters; -using CPUx86 = XSharp.Assembler.x86; -using Label = XSharp.Assembler.Label; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Mul)] - public class Mul : ILOp - { - public Mul(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSize = SizeOfType(xStackContent); - var xStackContentIsFloat = TypeIsFloat(xStackContent); - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - DoExecute(xStackContentSize, xStackContentIsFloat, BaseLabel); - } - - public static void DoExecute(uint xStackContentSize, bool xStackContentIsFloat, string aBaseLabel) - { - if (xStackContentSize > 4) - { - if (xStackContentIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.MulSD(XMM1, XMM0); - XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true); - } - else - { - // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32) - string Simple32Multiply = aBaseLabel + "Simple32Multiply"; - string MoveReturnValue = aBaseLabel + "MoveReturnValue"; - - // right value - // low - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true - // high - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 - - // left value - // low - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8 - // high - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 - - // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used - //mov RIGHT_HIGH to eax, is useable on Full 64 multiply - XS.Set(EAX, ESP, sourceDisplacement: 4); - XS.Or(EAX, ESP, sourceDisplacement: 12); - XS.Jump(CPUx86.ConditionalTestEnum.Zero, Simple32Multiply); - // Full 64 Multiply - - // copy again, or could change EAX - //TODO is there an opcode that does OR without change EAX? - XS.Set(EAX, ESP, sourceDisplacement: 4); - // eax contains already RIGHT_HIGH - // multiply with LEFT_LOW - XS.Multiply(ESP, displacement: 8); - // save result of LEFT_LOW * RIGHT_HIGH - XS.Set(ECX, EAX); - - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_HIGH - XS.Multiply(ESP, displacement: 12); - // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH - XS.Add(ECX, EAX); - - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_LOW - XS.Multiply(ESP, displacement: 8); - // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result - XS.Add(EDX, ECX); - - XS.Jump(MoveReturnValue); - - XS.Label(Simple32Multiply); - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_LOW - XS.Multiply(ESP, displacement: 8); - - XS.Label(MoveReturnValue); - // move high result to left high - XS.Set(ESP, EDX, destinationDisplacement: 12); - // move low result to left low - XS.Set(ESP, EAX, destinationDisplacement: 8); - // pop right 64 value - XS.Add(ESP, 8); - } - } - else - { - if (xStackContentIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.SSE.MulSS(XMM1, XMM0); - XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true); - } - else - { - XS.Pop(EAX); - XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32); - XS.Add(ESP, 4); - XS.Push(EAX); - } - } - } - } -} +using System; +using XSharp.Assembler.x86.SSE; + +using XSharp; +using static XSharp.XSRegisters; +using CPUx86 = XSharp.Assembler.x86; +using Label = XSharp.Assembler.Label; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Mul)] + public class Mul : ILOp + { + public Mul(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSize = SizeOfType(xStackContent); + var xStackContentIsFloat = TypeIsFloat(xStackContent); + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + DoExecute(xStackContentSize, xStackContentIsFloat, BaseLabel); + } + + public static void DoExecute(uint xStackContentSize, bool xStackContentIsFloat, string aBaseLabel) + { + if (xStackContentSize > 4) + { + if (xStackContentIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.MulSD(XMM1, XMM0); + XS.SSE2.MoveSD(RSP, XMM1, destinationIsIndirect: true); + } + else + { + // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32) + string Simple32Multiply = aBaseLabel + "Simple32Multiply"; + string MoveReturnValue = aBaseLabel + "MoveReturnValue"; + + // right value + // low + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true + // high + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 + + // left value + // low + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8 + // high + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 + + // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used + //mov RIGHT_HIGH to eax, is useable on Full 64 multiply + XS.Set(RAX, RSP, sourceDisplacement: 4); + XS.Or(RAX, RSP, sourceDisplacement: 12); + XS.Jump(CPUx86.ConditionalTestEnum.Zero, Simple32Multiply); + // Full 64 Multiply + + // copy again, or could change EAX + //TODO is there an opcode that does OR without change EAX? + XS.Set(RAX, RSP, sourceDisplacement: 4); + // eax contains already RIGHT_HIGH + // multiply with LEFT_LOW + XS.Multiply(RSP, displacement: 8); + // save result of LEFT_LOW * RIGHT_HIGH + XS.Set(RCX, RAX); + + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_HIGH + XS.Multiply(RSP, displacement: 12); + // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH + XS.Add(RCX, RAX); + + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_LOW + XS.Multiply(RSP, displacement: 8); + // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result + XS.Add(RDX, RCX); + + XS.Jump(MoveReturnValue); + + XS.Label(Simple32Multiply); + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_LOW + XS.Multiply(RSP, displacement: 8); + + XS.Label(MoveReturnValue); + // move high result to left high + XS.Set(RSP, RDX, destinationDisplacement: 12); + // move low result to left low + XS.Set(RSP, RAX, destinationDisplacement: 8); + // pop right 64 value + XS.Add(RSP, 8); + } + } + else + { + if (xStackContentIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.SSE.MulSS(XMM1, XMM0); + XS.SSE.MoveSS(RSP, XMM1, destinationIsIndirect: true); + } + else + { + XS.Pop(RAX); + XS.Multiply(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.Add(RSP, 4); + XS.Push(RAX); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Mul_Ovf.cs b/source/Cosmos.IL2CPU/IL/Mul_Ovf.cs index e796e007e..e22457917 100644 --- a/source/Cosmos.IL2CPU/IL/Mul_Ovf.cs +++ b/source/Cosmos.IL2CPU/IL/Mul_Ovf.cs @@ -1,105 +1,105 @@ -using System; - -using XSharp.Assembler; -using XSharp.Assembler.x86; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Mul_Ovf)] - public class Mul_Ovf : ILOp - { - public Mul_Ovf(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSize = SizeOfType(xStackContent); - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - DoExecute(xStackContentSize, BaseLabel); - } - - public static void DoExecute(uint xStackContentSize, string aBaseLabel) - { - //TODO: Throw System.OverflowException if the result won't fit in the type. - - if (xStackContentSize > 4) - { - // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32) - string Simple32Multiply = aBaseLabel + "Simple32Multiply"; - string MoveReturnValue = aBaseLabel + "MoveReturnValue"; - - // right value - // low - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true - // high - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 - - // left value - // low - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8 - // high - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 - - // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used - //mov RIGHT_HIGH to eax, is useable on Full 64 multiply - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - XS.Or(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 12); - XS.Jump(ConditionalTestEnum.Zero, Simple32Multiply); - // Full 64 Multiply - - // copy again, or could change EAX - //TODO is there an opcode that does OR without change EAX? - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - // eax contains already RIGHT_HIGH - // multiply with LEFT_LOW - XS.Multiply(XSRegisters.ESP, displacement: 8); - // save result of LEFT_LOW * RIGHT_HIGH - XS.Set(XSRegisters.ECX, XSRegisters.EAX); - - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_HIGH - XS.Multiply(XSRegisters.ESP, displacement: 12); - // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH - XS.Add(XSRegisters.ECX, XSRegisters.EAX); - - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_LOW - XS.Multiply(XSRegisters.ESP, displacement: 8); - // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result - XS.Add(XSRegisters.EDX, XSRegisters.ECX); - - XS.Jump(MoveReturnValue); - - XS.Label(Simple32Multiply); - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_LOW - XS.Multiply(XSRegisters.ESP, displacement: 8); - - XS.Label(MoveReturnValue); - // move high result to left high - XS.Set(ESP, EDX, destinationDisplacement: 12); - // move low result to left low - XS.Set(ESP, EAX, destinationDisplacement: 8); - // pop right 64 value - XS.Add(XSRegisters.ESP, 8); - } - else - { - XS.Pop(EAX); - XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32); - XS.Add(XSRegisters.ESP, 4); - XS.Push(XSRegisters.EAX); - } - } - - } -} +using System; + +using XSharp.Assembler; +using XSharp.Assembler.x86; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Mul_Ovf)] + public class Mul_Ovf : ILOp + { + public Mul_Ovf(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSize = SizeOfType(xStackContent); + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + DoExecute(xStackContentSize, BaseLabel); + } + + public static void DoExecute(uint xStackContentSize, string aBaseLabel) + { + //TODO: Throw System.OverflowException if the result won't fit in the type. + + if (xStackContentSize > 4) + { + // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32) + string Simple32Multiply = aBaseLabel + "Simple32Multiply"; + string MoveReturnValue = aBaseLabel + "MoveReturnValue"; + + // right value + // low + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true + // high + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 + + // left value + // low + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8 + // high + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 + + // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used + //mov RIGHT_HIGH to eax, is useable on Full 64 multiply + XS.Set(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 4); + XS.Or(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 12); + XS.Jump(ConditionalTestEnum.Zero, Simple32Multiply); + // Full 64 Multiply + + // copy again, or could change EAX + //TODO is there an opcode that does OR without change EAX? + XS.Set(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 4); + // eax contains already RIGHT_HIGH + // multiply with LEFT_LOW + XS.Multiply(XSRegisters.RSP, displacement: 8); + // save result of LEFT_LOW * RIGHT_HIGH + XS.Set(XSRegisters.RCX, XSRegisters.RAX); + + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_HIGH + XS.Multiply(XSRegisters.RSP, displacement: 12); + // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH + XS.Add(XSRegisters.RCX, XSRegisters.RAX); + + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_LOW + XS.Multiply(XSRegisters.RSP, displacement: 8); + // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result + XS.Add(XSRegisters.RDX, XSRegisters.RCX); + + XS.Jump(MoveReturnValue); + + XS.Label(Simple32Multiply); + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_LOW + XS.Multiply(XSRegisters.RSP, displacement: 8); + + XS.Label(MoveReturnValue); + // move high result to left high + XS.Set(RSP, RDX, destinationDisplacement: 12); + // move low result to left low + XS.Set(RSP, RAX, destinationDisplacement: 8); + // pop right 64 value + XS.Add(XSRegisters.RSP, 8); + } + else + { + XS.Pop(RAX); + XS.Multiply(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.Add(XSRegisters.RSP, 4); + XS.Push(XSRegisters.RAX); + } + } + + } +} diff --git a/source/Cosmos.IL2CPU/IL/Mul_Ovf_Un.cs b/source/Cosmos.IL2CPU/IL/Mul_Ovf_Un.cs index 0339f0aad..1fa3f3075 100644 --- a/source/Cosmos.IL2CPU/IL/Mul_Ovf_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Mul_Ovf_Un.cs @@ -1,104 +1,104 @@ -using System; - -using XSharp.Assembler; -using XSharp.Assembler.x86; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Mul_Ovf_Un)] - public class Mul_Ovf_Un : ILOp - { - public Mul_Ovf_Un(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSize = SizeOfType(xStackContent); - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - DoExecute(xStackContentSize, BaseLabel); - } - - public static void DoExecute(uint xStackContentSize, string aBaseLabel) - { - //TODO: Throw System.OverflowException if the result won't fit in the type. - - if (xStackContentSize > 4) - { - // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32) - string Simple32Multiply = aBaseLabel + "Simple32Multiply"; - string MoveReturnValue = aBaseLabel + "MoveReturnValue"; - - // right value - // low - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true - // high - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 - - // left value - // low - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8 - // high - // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 - - // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used - //mov RIGHT_HIGH to eax, is useable on Full 64 multiply - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - XS.Or(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 12); - XS.Jump(ConditionalTestEnum.Zero, Simple32Multiply); - // Full 64 Multiply - - // copy again, or could change EAX - //TODO is there an opcode that does OR without change EAX? - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - // eax contains already RIGHT_HIGH - // multiply with LEFT_LOW - XS.Multiply(XSRegisters.ESP, displacement: 8); - // save result of LEFT_LOW * RIGHT_HIGH - XS.Set(XSRegisters.ECX, XSRegisters.EAX); - - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_HIGH - XS.Multiply(XSRegisters.ESP, displacement: 12); - // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH - XS.Add(XSRegisters.ECX, XSRegisters.EAX); - - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_LOW - XS.Multiply(XSRegisters.ESP, displacement: 8); - // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result - XS.Add(XSRegisters.EDX, XSRegisters.ECX); - - XS.Jump(MoveReturnValue); - - XS.Label(Simple32Multiply); - //mov RIGHT_LOW to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - // multiply with LEFT_LOW - XS.Multiply(XSRegisters.ESP, displacement: 8); - - XS.Label(MoveReturnValue); - // move high result to left high - XS.Set(ESP, EDX, destinationDisplacement: 12); - // move low result to left low - XS.Set(ESP, EAX, destinationDisplacement: 8); - // pop right 64 value - XS.Add(XSRegisters.ESP, 8); - } - else - { - XS.Pop(XSRegisters.EAX); - XS.Multiply(ESP, isIndirect: true, size: RegisterSize.Int32); - XS.Add(XSRegisters.ESP, 4); - XS.Push(XSRegisters.EAX); - } - } - } -} +using System; + +using XSharp.Assembler; +using XSharp.Assembler.x86; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Mul_Ovf_Un)] + public class Mul_Ovf_Un : ILOp + { + public Mul_Ovf_Un(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSize = SizeOfType(xStackContent); + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + DoExecute(xStackContentSize, BaseLabel); + } + + public static void DoExecute(uint xStackContentSize, string aBaseLabel) + { + //TODO: Throw System.OverflowException if the result won't fit in the type. + + if (xStackContentSize > 4) + { + // div of both == LEFT_LOW * RIGHT_LOW + ((LEFT_LOW * RIGHT_HIGH + RIGHT_LOW * LEFT_HIGH) << 32) + string Simple32Multiply = aBaseLabel + "Simple32Multiply"; + string MoveReturnValue = aBaseLabel + "MoveReturnValue"; + + // right value + // low + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true + // high + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 + + // left value + // low + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 8 + // high + // SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 + + // compair LEFT_HIGH, RIGHT_HIGH , on zero only simple multiply is used + //mov RIGHT_HIGH to eax, is useable on Full 64 multiply + XS.Set(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 4); + XS.Or(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 12); + XS.Jump(ConditionalTestEnum.Zero, Simple32Multiply); + // Full 64 Multiply + + // copy again, or could change EAX + //TODO is there an opcode that does OR without change EAX? + XS.Set(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 4); + // eax contains already RIGHT_HIGH + // multiply with LEFT_LOW + XS.Multiply(XSRegisters.RSP, displacement: 8); + // save result of LEFT_LOW * RIGHT_HIGH + XS.Set(XSRegisters.RCX, XSRegisters.RAX); + + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_HIGH + XS.Multiply(XSRegisters.RSP, displacement: 12); + // add result of LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH + XS.Add(XSRegisters.RCX, XSRegisters.RAX); + + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_LOW + XS.Multiply(XSRegisters.RSP, displacement: 8); + // add LEFT_LOW * RIGHT_HIGH + RIGHT_LOW + LEFT_HIGH to high dword of last result + XS.Add(XSRegisters.RDX, XSRegisters.RCX); + + XS.Jump(MoveReturnValue); + + XS.Label(Simple32Multiply); + //mov RIGHT_LOW to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + // multiply with LEFT_LOW + XS.Multiply(XSRegisters.RSP, displacement: 8); + + XS.Label(MoveReturnValue); + // move high result to left high + XS.Set(RSP, RDX, destinationDisplacement: 12); + // move low result to left low + XS.Set(RSP, RAX, destinationDisplacement: 8); + // pop right 64 value + XS.Add(XSRegisters.RSP, 8); + } + else + { + XS.Pop(XSRegisters.RAX); + XS.Multiply(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.Add(XSRegisters.RSP, 4); + XS.Push(XSRegisters.RAX); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Neg.cs b/source/Cosmos.IL2CPU/IL/Neg.cs index 41c8febc2..d7a86dfcc 100644 --- a/source/Cosmos.IL2CPU/IL/Neg.cs +++ b/source/Cosmos.IL2CPU/IL/Neg.cs @@ -1,59 +1,59 @@ -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Neg)] - public class Neg : ILOp - { - public Neg(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSize = SizeOfType(xStackContent); - var xStackContentIsFloat = TypeIsFloat(xStackContent); - if (xStackContentSize > 4) - { - if (xStackContentIsFloat) - { - // There is no direct double negate instruction in SSE simply we do a XOR with 0x8000000000 to flip the sign bit - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: true); - XS.SSE2.MoveSD(ESP, XMM0, destinationIsIndirect: true); - } - else - { - XS.Pop(EBX); // low - XS.Pop(EAX); // high - XS.Negate(EBX); // set carry if EBX != 0 - XS.AddWithCarry(EAX, 0); - XS.Negate(EAX); - XS.Push(EAX); - XS.Push(EBX); - } - } - else - { - if (xStackContentIsFloat) - { - // There is no direct float negate instruction in SSE simply we do a XOR with 0x80000000 to flip the sign bit - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true); - XS.SSE.XorPS(XMM0, XMM1); - XS.SSE.MoveSS(ESP, XMM0, destinationIsIndirect: true); - } - else - { - XS.Pop(EAX); - XS.Negate(EAX); - XS.Push(EAX); - } - } - } - } -} +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Neg)] + public class Neg : ILOp + { + public Neg(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSize = SizeOfType(xStackContent); + var xStackContentIsFloat = TypeIsFloat(xStackContent); + if (xStackContentSize > 4) + { + if (xStackContentIsFloat) + { + // There is no direct double negate instruction in SSE simply we do a XOR with 0x8000000000 to flip the sign bit + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.SSE2.XorPD(XMM0, "__doublesignbit", sourceIsIndirect: true); + XS.SSE2.MoveSD(RSP, XMM0, destinationIsIndirect: true); + } + else + { + XS.Pop(RBX); // low + XS.Pop(RAX); // high + XS.Negate(RBX); // set carry if EBX != 0 + XS.AddWithCarry(RAX, 0); + XS.Negate(RAX); + XS.Push(RAX); + XS.Push(RBX); + } + } + else + { + if (xStackContentIsFloat) + { + // There is no direct float negate instruction in SSE simply we do a XOR with 0x80000000 to flip the sign bit + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.SSE.MoveSS(XMM1, "__floatsignbit", sourceIsIndirect: true); + XS.SSE.XorPS(XMM0, XMM1); + XS.SSE.MoveSS(RSP, XMM0, destinationIsIndirect: true); + } + else + { + XS.Pop(RAX); + XS.Negate(RAX); + XS.Push(RAX); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Newarr.cs b/source/Cosmos.IL2CPU/IL/Newarr.cs index d622b568f..02aafbc3d 100644 --- a/source/Cosmos.IL2CPU/IL/Newarr.cs +++ b/source/Cosmos.IL2CPU/IL/Newarr.cs @@ -1,58 +1,58 @@ -using System; -using System.Reflection; - -using IL2CPU.API; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Pushes an object reference to a new zero-based, one-dimensional array whose elements are of a specific type onto the evaluation stack. - /// - [OpCode(ILOpCode.Code.Newarr)] - public class Newarr : ILOp - { - public Newarr(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = (ILOpCodes.OpType)aOpCode; - uint xSize = SizeOfType(xType.Value); - - string xTypeID = GetTypeIDLabel(xType.Value); - MethodBase xCtor = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0]; - string xCtorName = LabelName.Get(xCtor); - - XS.Comment("Element Size = " + xSize); - XS.Pop(EAX); // element count - XS.Push(EAX); - XS.Set(EDX, xSize); - XS.Multiply(EDX); // total element size - XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); // total array size - XS.Push(EAX); - XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); - XS.Label(".AfterAlloc"); - XS.Pop(EAX); // location - XS.Pop(ESI); // element count - XS.Push(EAX); - XS.Push(ESP, isIndirect: true); - XS.Push(ESP, isIndirect: true); - // it's on the stack 3 times now, once from the return value, twice from the pushes; - - XS.Pop(EAX); - XS.Set(EBX, xTypeID, sourceIsIndirect: true); // array type id - XS.Set(EAX, EBX, destinationIsIndirect: true); // array type id - XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true); - XS.Set(EAX, ESI, destinationDisplacement: 8, destinationIsIndirect: true); // element count - XS.Set(EAX, xSize, destinationDisplacement: 12, destinationIsIndirect: true); // element size - XS.Push(0); - XS.Call(xCtorName); - XS.Push(0); - } - } -} +using System; +using System.Reflection; + +using IL2CPU.API; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Pushes an object reference to a new zero-based, one-dimensional array whose elements are of a specific type onto the evaluation stack. + /// + [OpCode(ILOpCode.Code.Newarr)] + public class Newarr : ILOp + { + public Newarr(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = (ILOpCodes.OpType)aOpCode; + uint xSize = SizeOfType(xType.Value); + + string xTypeID = GetTypeIDLabel(xType.Value); + MethodBase xCtor = typeof(Array).GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance)[0]; + string xCtorName = LabelName.Get(xCtor); + + XS.Comment("Element Size = " + xSize); + XS.Pop(RAX); // element count + XS.Push(RAX); + XS.Set(RDX, xSize); + XS.Multiply(RDX); // total element size + XS.Add(RAX, ObjectUtils.FieldDataOffset + 4); // total array size + XS.Push(RAX); + XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); + XS.Label(".AfterAlloc"); + XS.Pop(RAX); // location + XS.Pop(RSI); // element count + XS.Push(RAX); + XS.Push(RSP, isIndirect: true); + XS.Push(RSP, isIndirect: true); + // it's on the stack 3 times now, once from the return value, twice from the pushes; + + XS.Pop(RAX); + XS.Set(RBX, xTypeID, sourceIsIndirect: true); // array type id + XS.Set(RAX, RBX, destinationIsIndirect: true); // array type id + XS.Set(RAX, (uint)ObjectUtils.InstanceTypeEnum.Array, destinationDisplacement: 4, destinationIsIndirect: true); + XS.Set(RAX, RSI, destinationDisplacement: 8, destinationIsIndirect: true); // element count + XS.Set(RAX, xSize, destinationDisplacement: 12, destinationIsIndirect: true); // element size + XS.Push(0); + XS.Call(xCtorName); + XS.Push(0); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Newobj.cs b/source/Cosmos.IL2CPU/IL/Newobj.cs index b30a5d70c..df8350f15 100644 --- a/source/Cosmos.IL2CPU/IL/Newobj.cs +++ b/source/Cosmos.IL2CPU/IL/Newobj.cs @@ -1,308 +1,308 @@ -using System; -using System.Linq; -using System.Reflection; - -using IL2CPU.API; -using Cosmos.IL2CPU.ILOpCodes; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; -using CPUx86 = XSharp.Assembler.x86; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Newobj)] - public class Newobj : ILOp - { - public Newobj(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xMethod = (OpMethod)aOpCode; - var xCurrentLabel = GetLabel(aMethod, aOpCode); - var xType = xMethod.Value.DeclaringType; - - Assemble(Assembler, aMethod, xMethod, xCurrentLabel, xType, xMethod.Value, DebugEnabled); - } - - public static void Assemble(Assembler aAssembler, Il2cpuMethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor, bool debugEnabled) - { - // call cctor: - if (aMethod != null) - { - var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? Array.Empty()).SingleOrDefault(); - if (xCctor != null) - { - XS.Call(LabelName.Get(xCctor)); - EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck"); - XS.Label(".AfterCCTorExceptionCheck"); - } - } - - if (objectType.IsValueType) - { - #region Valuetypes - - XS.Comment("ValueType"); - XS.Comment("Type: " + objectType); - - /* - * Current sitation on stack: - * $ESP Arg - * $ESP+.. other items - * - * What should happen: - * + The stack should be increased to allow space to contain: - * + .ctor arguments - * + struct _pointer_ (ref to start of emptied space) - * + empty space for struct - * + arguments should be copied to the new place - * + old place where arguments were should be cleared - * + pointer should be set - * + call .ctor - */ - - // Size of return value - we need to make room for this on the stack. - var xStorageSize = Align(SizeOfType(objectType), 4); - XS.Comment("StorageSize: " + xStorageSize); - if (xStorageSize == 0) - { - throw new Exception("ValueType storage size cannot be 0."); - } - - uint xArgSize = 0; - var xParameterList = constructor.GetParameters(); - foreach (var xParam in xParameterList) - { - xArgSize = xArgSize + Align(SizeOfType(xParam.ParameterType), 4); - } - XS.Comment("ArgSize: " + xArgSize); - - // set source of args copy - XS.Set(ESI, ESP); - - // allocate space for struct - XS.Sub(ESP, xStorageSize + 4); - - // set destination and count of args copy - XS.Set(EDI, ESP); - XS.Set(ECX, xArgSize / 4); - - // move the args to their new location - new CPUx86.Movs { Size = 32, Prefixes = CPUx86.InstructionPrefixes.Repeat }; - - // set struct ptr - XS.Set(EAX, ESP); - XS.Add(EAX, xArgSize + 4); - XS.Set(ESP, EAX, destinationDisplacement: (int)xArgSize); - - XS.Push(EAX); - - var xOpType = new OpType(xMethod.OpCode, xMethod.Position, xMethod.NextPosition, xMethod.Value.DeclaringType, xMethod.CurrentExceptionRegion); - new Initobj(aAssembler).Execute(aMethod, xOpType, true); - - new Call(aAssembler).Execute(aMethod, xMethod); - - // Need to put these *after* the call because the Call pops the args from the stack - // and we have mucked about on the stack, so this makes it right before the next - // op. - - #endregion Valuetypes - } - else - { - // If not ValueType, then we need gc - - var xParams = constructor.GetParameters(); - - // array length + 8 - var xHasCalcSize = false; - - #region Special string handling - // try calculating size: - if (constructor.DeclaringType == typeof(string)) - { - if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char[])) - { - xHasCalcSize = true; - XS.Set(EAX, ESP, sourceDisplacement: 4, sourceIsIndirect: true); // address - XS.Set(EAX, EAX, sourceDisplacement: 8, sourceIsIndirect: true); // element count - XS.Set(EDX, 2); // element size - XS.Multiply(EDX); - XS.Push(EAX); - } - else if (xParams.Length == 3 - && (xParams[0].ParameterType == typeof(char[]) || xParams[0].ParameterType == typeof(char*)) - && xParams[1].ParameterType == typeof(int) - && xParams[2].ParameterType == typeof(int)) - { - xHasCalcSize = true; - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.ShiftLeft(EAX, 1); - XS.Push(EAX); - } - else if (xParams.Length == 2 - && xParams[0].ParameterType == typeof(char) - && xParams[1].ParameterType == typeof(int)) - { - xHasCalcSize = true; - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.ShiftLeft(EAX, 1); - XS.Push(EAX); - } - /* - * TODO see if something is needed in stack / register to make them really work - */ - else if (xParams.Length == 3 - && xParams[0].ParameterType == typeof(sbyte*) - && xParams[1].ParameterType == typeof(int) - && xParams[2].ParameterType == typeof(int)) - { - xHasCalcSize = true; - XS.Push(ESP, isIndirect: true); - } - else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(sbyte*)) - { - xHasCalcSize = true; - /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */ - var xSByteCountLabel = currentLabel + ".SByteCount"; - - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.Or(ECX, 0xFFFFFFFF); - - XS.Label(xSByteCountLabel); - - XS.Increment(EAX); - XS.Increment(ECX); - - XS.Compare(EAX, 0, destinationIsIndirect: true); - XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel); - - XS.Push(ECX); - } - else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char*)) - { - xHasCalcSize = true; - /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */ - // todo: does this actually work for empty strings? - var xSByteCountLabel = currentLabel + ".SByteCount"; - - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.Or(ECX, 0xFFFFFFFF); - - XS.Label(xSByteCountLabel); - - XS.Increment(EAX); // a char is two bytes - XS.Increment(EAX); - XS.Increment(ECX); - XS.Set(EBX, EAX, sourceIsIndirect: true); - XS.And(EBX, 0xFF); // Only compare the char - XS.Compare(EBX, 0); - XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel); - - XS.ShiftLeft(ECX, 1); // every character needs two bytes - XS.Push(ECX); - } - else if(xParams.Length == 1 && xParams[0].ParameterType == typeof(ReadOnlySpan)) - { - xHasCalcSize = true; - // push the lenght of the span as well - // ReadOnlySpan in memory is a Pointer and Length, simply dup the length and multiply by 2 to get the length to allocate - XS.Set(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: 4); - XS.ShiftLeft(EAX, 1); - XS.Push(EAX); - } - else - { - // You actually have to do something to implement a new ctor. For every ctor, newobj has to calculate the size of the string being allocated so that the GC can give enough space. - // If this is not done, it will seem to work until a new object is allocated in the space after the string overwriting the string data. This may only happen for long enough strings i.e. - // strings with more than one character - throw new NotImplementedException(); - } - } - #endregion Special string handling - - var xMemSize = GetStorageSize(objectType); - var xExtraSize = 12; // additional size for set values after alloc - XS.Push((uint)(xMemSize + xExtraSize)); - if (xHasCalcSize) - { - XS.Pop(EAX); - XS.Add(ESP, EAX, destinationIsIndirect: true); - } - - // todo: probably we want to check for exceptions after calling Alloc - XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); - XS.Label(".AfterAlloc"); - XS.Push(ESP, isIndirect: true); - XS.Push(ESP, isIndirect: true); - // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes - - var strTypeId = GetTypeIDLabel(constructor.DeclaringType); - - XS.Pop(EAX); - XS.Set(EBX, strTypeId, sourceIsIndirect: true); - XS.Set(EAX, EBX, destinationIsIndirect: true); - XS.Set(EAX, (uint)ObjectUtils.InstanceTypeEnum.NormalObject, destinationDisplacement: 4, destinationIsIndirect: true, size: RegisterSize.Int32); - XS.Set(EAX, xMemSize, destinationDisplacement: 8, destinationIsIndirect: true, size: RegisterSize.Int32); - var xSize = (uint)(from item in xParams - let xQSize = Align(SizeOfType(item.ParameterType), 4) - select (int)xQSize).Take(xParams.Length).Sum(); - XS.Push(0); - - foreach (var xParam in xParams) - { - var xParamSize = Align(SizeOfType(xParam.ParameterType), 4); - XS.Comment($"Arg {xParam.Name}: {xParamSize}"); - for (var i = 0; i < xParamSize; i += 4) - { - XS.Push(ESP, isIndirect: true, displacement: (int)(xSize + 8)); - } - } - - XS.Call(LabelName.Get(constructor)); - // should the complete error handling happen by ILOp.EmitExceptionLogic? - if (aMethod != null) - { - // todo: only happening for real methods now, not for ctor's ? - XS.Test(ECX, 2); - var xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString(); - XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel); - - PushAlignedParameterSize(constructor); - - // an exception occurred, we need to cleanup the stack, and jump to the exit - XS.Add(ESP, 4); - - new Comment(aAssembler, "[ Newobj.Execute cleanup end ]"); - XS.Jump(GetLabel(aMethod) + AppAssembler.EndOfMethodLabelNameException); - XS.Label(xNoErrorLabel); - } - XS.Pop(EAX); - - PushAlignedParameterSize(constructor); - - XS.Push(EAX); - XS.Push(0); - } - } - - private static void PushAlignedParameterSize(MethodBase aMethod) - { - ParameterInfo[] xParams = aMethod.GetParameters(); - - uint xSize; - XS.Comment("[ Newobj.PushAlignedParameterSize start count = " + xParams.Length.ToString() + " ]"); - for (var i = 0; i < xParams.Length; i++) - { - xSize = SizeOfType(xParams[i].ParameterType); - XS.Add(ESP, Align(xSize, 4)); - } - XS.Comment("[ Newobj.PushAlignedParameterSize end ]"); - } - } -} +using System; +using System.Linq; +using System.Reflection; + +using IL2CPU.API; +using Cosmos.IL2CPU.ILOpCodes; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; +using CPUx86 = XSharp.Assembler.x86; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Newobj)] + public class Newobj : ILOp + { + public Newobj(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xMethod = (OpMethod)aOpCode; + var xCurrentLabel = GetLabel(aMethod, aOpCode); + var xType = xMethod.Value.DeclaringType; + + Assemble(Assembler, aMethod, xMethod, xCurrentLabel, xType, xMethod.Value, DebugEnabled); + } + + public static void Assemble(Assembler aAssembler, Il2cpuMethodInfo aMethod, OpMethod xMethod, string currentLabel, Type objectType, MethodBase constructor, bool debugEnabled) + { + // call cctor: + if (aMethod != null) + { + var xCctor = (objectType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic) ?? Array.Empty()).SingleOrDefault(); + if (xCctor != null) + { + XS.Call(LabelName.Get(xCctor)); + EmitExceptionLogic(aAssembler, aMethod, xMethod, true, null, ".AfterCCTorExceptionCheck"); + XS.Label(".AfterCCTorExceptionCheck"); + } + } + + if (objectType.IsValueType) + { + #region Valuetypes + + XS.Comment("ValueType"); + XS.Comment("Type: " + objectType); + + /* + * Current sitation on stack: + * $ESP Arg + * $ESP+.. other items + * + * What should happen: + * + The stack should be increased to allow space to contain: + * + .ctor arguments + * + struct _pointer_ (ref to start of emptied space) + * + empty space for struct + * + arguments should be copied to the new place + * + old place where arguments were should be cleared + * + pointer should be set + * + call .ctor + */ + + // Size of return value - we need to make room for this on the stack. + var xStorageSize = Align(SizeOfType(objectType), 4); + XS.Comment("StorageSize: " + xStorageSize); + if (xStorageSize == 0) + { + throw new Exception("ValueType storage size cannot be 0."); + } + + uint xArgSize = 0; + var xParameterList = constructor.GetParameters(); + foreach (var xParam in xParameterList) + { + xArgSize = xArgSize + Align(SizeOfType(xParam.ParameterType), 4); + } + XS.Comment("ArgSize: " + xArgSize); + + // set source of args copy + XS.Set(RSI, RSP); + + // allocate space for struct + XS.Sub(RSP, xStorageSize + 4); + + // set destination and count of args copy + XS.Set(RDI, RSP); + XS.Set(RCX, xArgSize / 4); + + // move the args to their new location + new CPUx86.Movs { Size = 32, Prefixes = CPUx86.InstructionPrefixes.Repeat }; + + // set struct ptr + XS.Set(RAX, RSP); + XS.Add(RAX, xArgSize + 4); + XS.Set(RSP, RAX, destinationDisplacement: (int)xArgSize); + + XS.Push(RAX); + + var xOpType = new OpType(xMethod.OpCode, xMethod.Position, xMethod.NextPosition, xMethod.Value.DeclaringType, xMethod.CurrentExceptionRegion); + new Initobj(aAssembler).Execute(aMethod, xOpType, true); + + new Call(aAssembler).Execute(aMethod, xMethod); + + // Need to put these *after* the call because the Call pops the args from the stack + // and we have mucked about on the stack, so this makes it right before the next + // op. + + #endregion Valuetypes + } + else + { + // If not ValueType, then we need gc + + var xParams = constructor.GetParameters(); + + // array length + 8 + var xHasCalcSize = false; + + #region Special string handling + // try calculating size: + if (constructor.DeclaringType == typeof(string)) + { + if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char[])) + { + xHasCalcSize = true; + XS.Set(RAX, RSP, sourceDisplacement: 4, sourceIsIndirect: true); // address + XS.Set(RAX, RAX, sourceDisplacement: 8, sourceIsIndirect: true); // element count + XS.Set(RDX, 2); // element size + XS.Multiply(RDX); + XS.Push(RAX); + } + else if (xParams.Length == 3 + && (xParams[0].ParameterType == typeof(char[]) || xParams[0].ParameterType == typeof(char*)) + && xParams[1].ParameterType == typeof(int) + && xParams[2].ParameterType == typeof(int)) + { + xHasCalcSize = true; + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.ShiftLeft(RAX, 1); + XS.Push(RAX); + } + else if (xParams.Length == 2 + && xParams[0].ParameterType == typeof(char) + && xParams[1].ParameterType == typeof(int)) + { + xHasCalcSize = true; + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.ShiftLeft(RAX, 1); + XS.Push(RAX); + } + /* + * TODO see if something is needed in stack / register to make them really work + */ + else if (xParams.Length == 3 + && xParams[0].ParameterType == typeof(sbyte*) + && xParams[1].ParameterType == typeof(int) + && xParams[2].ParameterType == typeof(int)) + { + xHasCalcSize = true; + XS.Push(RSP, isIndirect: true); + } + else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(sbyte*)) + { + xHasCalcSize = true; + /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */ + var xSByteCountLabel = currentLabel + ".SByteCount"; + + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.Or(RCX, 0xFFFFFFFF); + + XS.Label(xSByteCountLabel); + + XS.Increment(RAX); + XS.Increment(RCX); + + XS.Compare(RAX, 0, destinationIsIndirect: true); + XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel); + + XS.Push(RCX); + } + else if (xParams.Length == 1 && xParams[0].ParameterType == typeof(char*)) + { + xHasCalcSize = true; + /* xParams[0] contains a C / ASCII Z string the following ASM is de facto the C strlen() function */ + // todo: does this actually work for empty strings? + var xSByteCountLabel = currentLabel + ".SByteCount"; + + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.Or(RCX, 0xFFFFFFFF); + + XS.Label(xSByteCountLabel); + + XS.Increment(RAX); // a char is two bytes + XS.Increment(RAX); + XS.Increment(RCX); + XS.Set(RBX, RAX, sourceIsIndirect: true); + XS.And(RBX, 0xFF); // Only compare the char + XS.Compare(RBX, 0); + XS.Jump(CPUx86.ConditionalTestEnum.NotEqual, xSByteCountLabel); + + XS.ShiftLeft(RCX, 1); // every character needs two bytes + XS.Push(RCX); + } + else if(xParams.Length == 1 && xParams[0].ParameterType == typeof(ReadOnlySpan)) + { + xHasCalcSize = true; + // push the lenght of the span as well + // ReadOnlySpan in memory is a Pointer and Length, simply dup the length and multiply by 2 to get the length to allocate + XS.Set(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: 4); + XS.ShiftLeft(RAX, 1); + XS.Push(RAX); + } + else + { + // You actually have to do something to implement a new ctor. For every ctor, newobj has to calculate the size of the string being allocated so that the GC can give enough space. + // If this is not done, it will seem to work until a new object is allocated in the space after the string overwriting the string data. This may only happen for long enough strings i.e. + // strings with more than one character + throw new NotImplementedException(); + } + } + #endregion Special string handling + + var xMemSize = GetStorageSize(objectType); + var xExtraSize = 12; // additional size for set values after alloc + XS.Push((uint)(xMemSize + xExtraSize)); + if (xHasCalcSize) + { + XS.Pop(RAX); + XS.Add(RSP, RAX, destinationIsIndirect: true); + } + + // todo: probably we want to check for exceptions after calling Alloc + XS.Call(LabelName.Get(GCImplementationRefs.AllocNewObjectRef)); + XS.Label(".AfterAlloc"); + XS.Push(RSP, isIndirect: true); + XS.Push(RSP, isIndirect: true); + // it's on the stack now 3 times. Once from the Alloc return value, twice from the pushes + + var strTypeId = GetTypeIDLabel(constructor.DeclaringType); + + XS.Pop(RAX); + XS.Set(RBX, strTypeId, sourceIsIndirect: true); + XS.Set(RAX, RBX, destinationIsIndirect: true); + XS.Set(RAX, (uint)ObjectUtils.InstanceTypeEnum.NormalObject, destinationDisplacement: 4, destinationIsIndirect: true, size: RegisterSize.Long64); + XS.Set(RAX, xMemSize, destinationDisplacement: 8, destinationIsIndirect: true, size: RegisterSize.Long64); + var xSize = (uint)(from item in xParams + let xQSize = Align(SizeOfType(item.ParameterType), 4) + select (int)xQSize).Take(xParams.Length).Sum(); + XS.Push(0); + + foreach (var xParam in xParams) + { + var xParamSize = Align(SizeOfType(xParam.ParameterType), 4); + XS.Comment($"Arg {xParam.Name}: {xParamSize}"); + for (var i = 0; i < xParamSize; i += 4) + { + XS.Push(RSP, isIndirect: true, displacement: (int)(xSize + 8)); + } + } + + XS.Call(LabelName.Get(constructor)); + // should the complete error handling happen by ILOp.EmitExceptionLogic? + if (aMethod != null) + { + // todo: only happening for real methods now, not for ctor's ? + XS.Test(RCX, 2); + var xNoErrorLabel = currentLabel + ".NoError" + LabelName.LabelCount.ToString(); + XS.Jump(CPUx86.ConditionalTestEnum.Equal, xNoErrorLabel); + + PushAlignedParameterSize(constructor); + + // an exception occurred, we need to cleanup the stack, and jump to the exit + XS.Add(RSP, 4); + + new Comment(aAssembler, "[ Newobj.Execute cleanup end ]"); + XS.Jump(GetLabel(aMethod) + AppAssembler.EndOfMethodLabelNameException); + XS.Label(xNoErrorLabel); + } + XS.Pop(RAX); + + PushAlignedParameterSize(constructor); + + XS.Push(RAX); + XS.Push(0); + } + } + + private static void PushAlignedParameterSize(MethodBase aMethod) + { + ParameterInfo[] xParams = aMethod.GetParameters(); + + uint xSize; + XS.Comment("[ Newobj.PushAlignedParameterSize start count = " + xParams.Length.ToString() + " ]"); + for (var i = 0; i < xParams.Length; i++) + { + xSize = SizeOfType(xParams[i].ParameterType); + XS.Add(RSP, Align(xSize, 4)); + } + XS.Comment("[ Newobj.PushAlignedParameterSize end ]"); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Not.cs b/source/Cosmos.IL2CPU/IL/Not.cs index 3b61f9b00..e881dd56a 100644 --- a/source/Cosmos.IL2CPU/IL/Not.cs +++ b/source/Cosmos.IL2CPU/IL/Not.cs @@ -1,36 +1,36 @@ -using System; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Not)] - public class Not : ILOp - { - public Not(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - - if (xSize <= 4) - { - XS.Not(ESP, isIndirect: true, size: RegisterSize.Int32); - } - else if (xSize <= 8) - { - XS.Not(ESP, isIndirect: true, size: RegisterSize.Int32); - XS.Not(ESP, displacement: 4, size: RegisterSize.Int32); - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Not.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Not)] + public class Not : ILOp + { + public Not(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + + if (xSize <= 4) + { + XS.Not(RSP, isIndirect: true, size: RegisterSize.Long64); + } + else if (xSize <= 8) + { + XS.Not(RSP, isIndirect: true, size: RegisterSize.Long64); + XS.Not(RSP, displacement: 4, size: RegisterSize.Long64); + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Not.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Or.cs b/source/Cosmos.IL2CPU/IL/Or.cs index 72a6cb99b..be3f2eb49 100644 --- a/source/Cosmos.IL2CPU/IL/Or.cs +++ b/source/Cosmos.IL2CPU/IL/Or.cs @@ -1,54 +1,54 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Or)] - public class Or : ILOp - { - public Or(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackContent = aOpCode.StackPopTypes[0]; - var xStackContentSecond = aOpCode.StackPopTypes[1]; - var xStackContentSize = SizeOfType(xStackContent); - var xStackContentSecondSize = SizeOfType(xStackContentSecond); - var xSize = Math.Max(xStackContentSize, xStackContentSecondSize); - - if (Align(xStackContentSize, 4) != Align(xStackContentSecondSize, 4)) - { - throw new NotSupportedException("Operands have different size!"); - } - if (xSize > 8) - { - throw new NotImplementedException("StackSize>8 not supported"); - } - - if (xSize > 4) - { - // [ESP] is low part - // [ESP + 4] is high part - // [ESP + 8] is low part - // [ESP + 12] is high part - XS.Pop(EAX); - XS.Pop(EDX); - // [ESP] is low part - // [ESP + 4] is high part - XS.Or(ESP, EAX, destinationIsIndirect: true); - XS.Or(ESP, EDX, destinationDisplacement: 4); - } - else - { - XS.Pop(EAX); - XS.Or(ESP, EAX, destinationIsIndirect: true); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Or)] + public class Or : ILOp + { + public Or(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackContent = aOpCode.StackPopTypes[0]; + var xStackContentSecond = aOpCode.StackPopTypes[1]; + var xStackContentSize = SizeOfType(xStackContent); + var xStackContentSecondSize = SizeOfType(xStackContentSecond); + var xSize = Math.Max(xStackContentSize, xStackContentSecondSize); + + if (Align(xStackContentSize, 4) != Align(xStackContentSecondSize, 4)) + { + throw new NotSupportedException("Operands have different size!"); + } + if (xSize > 8) + { + throw new NotImplementedException("StackSize>8 not supported"); + } + + if (xSize > 4) + { + // [ESP] is low part + // [ESP + 4] is high part + // [ESP + 8] is low part + // [ESP + 12] is high part + XS.Pop(RAX); + XS.Pop(RDX); + // [ESP] is low part + // [ESP + 4] is high part + XS.Or(RSP, RAX, destinationIsIndirect: true); + XS.Or(RSP, RDX, destinationDisplacement: 4); + } + else + { + XS.Pop(RAX); + XS.Or(RSP, RAX, destinationIsIndirect: true); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Pop.cs b/source/Cosmos.IL2CPU/IL/Pop.cs index c7c6e59bc..7870ed59e 100644 --- a/source/Cosmos.IL2CPU/IL/Pop.cs +++ b/source/Cosmos.IL2CPU/IL/Pop.cs @@ -1,22 +1,22 @@ -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Pop)] - public class Pop : ILOp - { - public Pop(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - // todo: implement exception support. - var xSize = SizeOfType(aOpCode.StackPopTypes[0]); - XS.Add(ESP, Align(xSize, 4)); - } - } -} +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Pop)] + public class Pop : ILOp + { + public Pop(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + // todo: implement exception support. + var xSize = SizeOfType(aOpCode.StackPopTypes[0]); + XS.Add(RSP, Align(xSize, 4)); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Refanytype.cs b/source/Cosmos.IL2CPU/IL/Refanytype.cs index 2e6bf92a0..f7df6e330 100644 --- a/source/Cosmos.IL2CPU/IL/Refanytype.cs +++ b/source/Cosmos.IL2CPU/IL/Refanytype.cs @@ -1,27 +1,27 @@ -using System; -using XSharp; -using XSharp.Assembler; - -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Refanytype)] - public class Refanytype : ILOp - { - public Refanytype(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - // we have object on stack, so type, address and want only the type to remain - DoNullReferenceCheck(Assembler, DebugEnabled, 0); - XS.Pop(EAX); - XS.Exchange(BX, BX); //TODO: Are we sure that we want to push a long? Isnt the type only an int? - XS.Push(EAX, isIndirect: true, displacement: 0); - XS.Push(EAX, isIndirect: true, displacement: 4); - } - } -} +using System; +using XSharp; +using XSharp.Assembler; + +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Refanytype)] + public class Refanytype : ILOp + { + public Refanytype(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + // we have object on stack, so type, address and want only the type to remain + DoNullReferenceCheck(Assembler, DebugEnabled, 0); + XS.Pop(RAX); + XS.Exchange(BX, BX); //TODO: Are we sure that we want to push a long? Isnt the type only an int? + XS.Push(RAX, isIndirect: true, displacement: 0); + XS.Push(RAX, isIndirect: true, displacement: 4); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Rem.cs b/source/Cosmos.IL2CPU/IL/Rem.cs index 53d0c137e..3145c9ad3 100644 --- a/source/Cosmos.IL2CPU/IL/Rem.cs +++ b/source/Cosmos.IL2CPU/IL/Rem.cs @@ -1,208 +1,208 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Rem)] - public class Rem : ILOp - { - public Rem(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); - var xIsFloat = TypeIsFloat(xStackItem); - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; - - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Rem.cs->Error: StackSize > 8 not supported"); - } - else if (xSize > 4) - { - if (xIsFloat) - { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); - XS.SSE2.XorPD(XMM2, XMM2); - XS.SSE2.DivSD(XMM1, XMM0); - XS.SSE2.MoveSD(ESP, XMM2, destinationIsIndirect: true); - } - else - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LabelShiftRight = BaseLabel + "ShiftRightLoop"; - string LabelNoLoop = BaseLabel + "NoLoop"; - string LabelEnd = BaseLabel + "End"; - - // divisor - //low - XS.Set(ESI, ESP, sourceIsIndirect: true); - //high - XS.Set(EDI, ESP, sourceDisplacement: 4); - - XS.Xor(EAX, EAX); - XS.Or(EAX, ESI); - XS.Or(EAX, EDI); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - //dividend - // low - XS.Set(EAX, ESP, sourceDisplacement: 8); - //high - XS.Set(EDX, ESP, sourceDisplacement: 12); - - // pop both 8 byte values - XS.Add(ESP, 16); - - // set flags - XS.Or(EDI, EDI); - - // if high dword of divisor is already zero, we dont need the loop - XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); - - // set ecx to zero for counting the shift operations - XS.Xor(ECX, ECX); - - // push most significant bit of dividend, because the sign of the remainder is the sign of the dividend - XS.Set(EBX, EDX); - XS.Push(EBX); - - XS.Compare(EDI, 0x80000000); - XS.Jump(ConditionalTestEnum.Below, BaseLabel + "divisor_no_neg"); - - XS.Negate(ESI); - XS.AddWithCarry(EDI, 0); - XS.Negate(EDI); - - XS.Label(BaseLabel + "divisor_no_neg"); - - XS.Compare(EDX, 0x80000000); - XS.Jump(ConditionalTestEnum.Below, BaseLabel + "dividend_no_neg"); - - XS.Negate(EAX); - XS.AddWithCarry(EDX, 0); - XS.Negate(EDX); - - XS.Label(BaseLabel + "dividend_no_neg"); - - XS.Label(LabelShiftRight); - - // shift divisor 1 bit right - XS.ShiftRightDouble(ESI, EDI, 1); - XS.ShiftRight(EDI, 1); - - // increment shift counter - XS.Increment(ECX); - - // set flags - //XS.Or(EDI, EDI); - XS.Set(EBX, ESI); - XS.And(EBX, 0x80000000); - XS.Or(EBX, EDI); - // loop while high dword of divisor is not zero or most significant bit of low dword of divisor is set - XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); - - // shift the dividend now in one step - XS.ShiftRightDouble(EAX, EDX, CL); - // shift dividend CL bits right - XS.ShiftRight(EDX, CL); - - // so we shifted both, so we have near the same relation as original values - // divide this - XS.Divide(ESI); - - XS.Xor(EAX, EAX); - - // shift the remainder in one step - XS.ShiftLeftDouble(EAX, EDX, CL); - // shift lower dword of remainder CL bits left - XS.ShiftLeft(EDX, CL); - - // pop most significant bit of result - XS.Pop(EBX); - - XS.Compare(EBX, 0x80000000); - XS.Jump(ConditionalTestEnum.Below, BaseLabel + "_remainder_no_neg"); - - XS.Negate(EDX); - XS.AddWithCarry(EAX, 0); - XS.Negate(EAX); - - XS.Label(BaseLabel + "_remainder_no_neg"); - - // save result to stack - XS.Push(EAX); - XS.Push(EDX); - - //TODO: implement proper derivation correction and overflow detection - - XS.Jump(LabelEnd); - - XS.Label(LabelNoLoop); - //save high dividend - XS.Set(ECX, EAX); - XS.Set(EAX, EDX); - // extend that sign is in edx - XS.SignExtendAX(RegisterSize.Int32); - // divide high part - XS.IntegerDivide(ESI); - XS.Set(EAX, ECX); - // divide low part - XS.Divide(ESI); - // save low result - XS.Push(0); - XS.Push(EDX); - - XS.Label(LabelEnd); - } - } - else - { - if (xIsFloat) - { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.XorPS(XMM2, XMM2); - XS.SSE.DivSS(XMM1, XMM0); - XS.Sub(ESP, 4); - XS.SSE.MoveSS(ESP, XMM2, destinationIsIndirect: true); - } - else - { - XS.Pop(ECX); - - XS.Test(ECX, ECX); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - XS.Pop(EAX); - - XS.SignExtendAX(RegisterSize.Int32); - - XS.IntegerDivide(ECX); - XS.Push(EDX); - } - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Rem)] + public class Rem : ILOp + { + public Rem(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); + var xIsFloat = TypeIsFloat(xStackItem); + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; + + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Rem.cs->Error: StackSize > 8 not supported"); + } + else if (xSize > 4) + { + if (xIsFloat) + { + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); + XS.SSE2.XorPD(XMM2, XMM2); + XS.SSE2.DivSD(XMM1, XMM0); + XS.SSE2.MoveSD(RSP, XMM2, destinationIsIndirect: true); + } + else + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LabelShiftRight = BaseLabel + "ShiftRightLoop"; + string LabelNoLoop = BaseLabel + "NoLoop"; + string LabelEnd = BaseLabel + "End"; + + // divisor + //low + XS.Set(RSI, RSP, sourceIsIndirect: true); + //high + XS.Set(RDI, RSP, sourceDisplacement: 4); + + XS.Xor(RAX, RAX); + XS.Or(RAX, RSI); + XS.Or(RAX, RDI); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + //dividend + // low + XS.Set(RAX, RSP, sourceDisplacement: 8); + //high + XS.Set(RDX, RSP, sourceDisplacement: 12); + + // pop both 8 byte values + XS.Add(RSP, 16); + + // set flags + XS.Or(RDI, RDI); + + // if high dword of divisor is already zero, we dont need the loop + XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); + + // set ecx to zero for counting the shift operations + XS.Xor(RCX, RCX); + + // push most significant bit of dividend, because the sign of the remainder is the sign of the dividend + XS.Set(RBX, RDX); + XS.Push(RBX); + + XS.Compare(RDI, 0x80000000); + XS.Jump(ConditionalTestEnum.Below, BaseLabel + "divisor_no_neg"); + + XS.Negate(RSI); + XS.AddWithCarry(RDI, 0); + XS.Negate(RDI); + + XS.Label(BaseLabel + "divisor_no_neg"); + + XS.Compare(RDX, 0x80000000); + XS.Jump(ConditionalTestEnum.Below, BaseLabel + "dividend_no_neg"); + + XS.Negate(RAX); + XS.AddWithCarry(RDX, 0); + XS.Negate(RDX); + + XS.Label(BaseLabel + "dividend_no_neg"); + + XS.Label(LabelShiftRight); + + // shift divisor 1 bit right + XS.ShiftRightDouble(RSI, RDI, 1); + XS.ShiftRight(RDI, 1); + + // increment shift counter + XS.Increment(RCX); + + // set flags + //XS.Or(EDI, EDI); + XS.Set(RBX, RSI); + XS.And(RBX, 0x80000000); + XS.Or(RBX, RDI); + // loop while high dword of divisor is not zero or most significant bit of low dword of divisor is set + XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); + + // shift the dividend now in one step + XS.ShiftRightDouble(RAX, RDX, CL); + // shift dividend CL bits right + XS.ShiftRight(RDX, CL); + + // so we shifted both, so we have near the same relation as original values + // divide this + XS.Divide(RSI); + + XS.Xor(RAX, RAX); + + // shift the remainder in one step + XS.ShiftLeftDouble(RAX, RDX, CL); + // shift lower dword of remainder CL bits left + XS.ShiftLeft(RDX, CL); + + // pop most significant bit of result + XS.Pop(RBX); + + XS.Compare(RBX, 0x80000000); + XS.Jump(ConditionalTestEnum.Below, BaseLabel + "_remainder_no_neg"); + + XS.Negate(RDX); + XS.AddWithCarry(RAX, 0); + XS.Negate(RAX); + + XS.Label(BaseLabel + "_remainder_no_neg"); + + // save result to stack + XS.Push(RAX); + XS.Push(RDX); + + //TODO: implement proper derivation correction and overflow detection + + XS.Jump(LabelEnd); + + XS.Label(LabelNoLoop); + //save high dividend + XS.Set(RCX, RAX); + XS.Set(RAX, RDX); + // extend that sign is in edx + XS.SignExtendAX(RegisterSize.Long64); + // divide high part + XS.IntegerDivide(RSI); + XS.Set(RAX, RCX); + // divide low part + XS.Divide(RSI); + // save low result + XS.Push(0); + XS.Push(RDX); + + XS.Label(LabelEnd); + } + } + else + { + if (xIsFloat) + { + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.XorPS(XMM2, XMM2); + XS.SSE.DivSS(XMM1, XMM0); + XS.Sub(RSP, 4); + XS.SSE.MoveSS(RSP, XMM2, destinationIsIndirect: true); + } + else + { + XS.Pop(RCX); + + XS.Test(RCX, RCX); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + XS.Pop(RAX); + + XS.SignExtendAX(RegisterSize.Long64); + + XS.IntegerDivide(RCX); + XS.Push(RDX); + } + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Rem_Un.cs b/source/Cosmos.IL2CPU/IL/Rem_Un.cs index f8f9fb5ec..947af1cc1 100644 --- a/source/Cosmos.IL2CPU/IL/Rem_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Rem_Un.cs @@ -1,157 +1,157 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - /// - /// Divides two unsigned values and pushes the remainder onto the evaluation stack. - /// - [OpCode(ILOpCode.Code.Rem_Un)] - public class Rem_Un : ILOp - { - public Rem_Un(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xStackItem = aOpCode.StackPopTypes[0]; - var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; - - if (TypeIsFloat(xStackItem)) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Rem_Un.cs->Error: Expected unsigned integer operands but got float!"); - } - - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Rem_Un.cs->Error: StackSize > 8 not supported"); - } - else if (xSize > 4) - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LabelShiftRight = BaseLabel + "ShiftRightLoop"; - string LabelNoLoop = BaseLabel + "NoLoop"; - string LabelEnd = BaseLabel + "End"; - - // divisor - //low - XS.Set(ESI, ESP, sourceIsIndirect: true); - //high - XS.Set(EDI, ESP, sourceDisplacement: 4); - - XS.Xor(EAX, EAX); - XS.Or(EAX, ESI); - XS.Or(EAX, EDI); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - //dividend - // low - XS.Set(EAX, ESP, sourceDisplacement: 8); - //high - XS.Set(EDX, ESP, sourceDisplacement: 12); - - // pop both 8 byte values - XS.Add(ESP, 16); - - // set flags - XS.Or(EDI, EDI); - // if high dword of divisor is already zero, we dont need the loop - XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); - - // set ecx to zero for counting the shift operations - XS.Xor(ECX, ECX); - - XS.Label(LabelShiftRight); - - // shift divisor 1 bit right - XS.ShiftRightDouble(ESI, EDI, 1); - XS.ShiftRight(EDI, 1); - - // increment shift counter - XS.Increment(ECX); - - // set flags - XS.Or(EDI, EDI); - // loop while high dword of divisor till it is zero - XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); - - // shift the dividend now in one step - XS.ShiftRightDouble(EAX, EDX, CL); - // shift dividend CL bits right - XS.ShiftRight(EDX, CL); - - // so we shifted both, so we have near the same relation as original values - // divide this - XS.Divide(ESI); - - // set eax to zero - XS.Xor(EAX, EAX); - - // shift the remainder in one step - XS.ShiftLeftDouble(EAX, EDX, CL); - // shift lower dword of remainder CL bits left - XS.ShiftLeft(EDX, CL); - - // save remainder to stack - XS.Push(EAX); - XS.Push(EDX); - - //TODO: implement proper derivation correction and overflow detection - - XS.Jump(LabelEnd); - - XS.Label(LabelNoLoop); - - //save high dividend - XS.Set(ECX, EAX); - XS.Set(EAX, EDX); - - // zero EDX, so that high part is zero -> reduce overflow case - XS.Xor(EDX, EDX); - - // divide high part - XS.Divide(ESI); - XS.Set(EAX, ECX); - - // divide low part - XS.Divide(ESI); - - // save remainder result - XS.Push(0); - XS.Push(EDX); - - XS.Label(LabelEnd); - } - else - { - XS.Pop(ECX); - - XS.Test(ECX, ECX); - XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); - - XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); - - XS.Label(xNoDivideByZeroExceptionLabel); - - XS.Pop(EAX); - - XS.Xor(EDX, EDX); - - XS.Divide(ECX); - XS.Push(EDX); - } - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + /// + /// Divides two unsigned values and pushes the remainder onto the evaluation stack. + /// + [OpCode(ILOpCode.Code.Rem_Un)] + public class Rem_Un : ILOp + { + public Rem_Un(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xStackItem = aOpCode.StackPopTypes[0]; + var xSize = Math.Max(SizeOfType(xStackItem), SizeOfType(aOpCode.StackPopTypes[1])); + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoDivideByZeroExceptionLabel = xBaseLabel + "_NoDivideByZeroException"; + + if (TypeIsFloat(xStackItem)) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Rem_Un.cs->Error: Expected unsigned integer operands but got float!"); + } + + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Rem_Un.cs->Error: StackSize > 8 not supported"); + } + else if (xSize > 4) + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LabelShiftRight = BaseLabel + "ShiftRightLoop"; + string LabelNoLoop = BaseLabel + "NoLoop"; + string LabelEnd = BaseLabel + "End"; + + // divisor + //low + XS.Set(RSI, RSP, sourceIsIndirect: true); + //high + XS.Set(RDI, RSP, sourceDisplacement: 4); + + XS.Xor(RAX, RAX); + XS.Or(RAX, RSI); + XS.Or(RAX, RDI); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + //dividend + // low + XS.Set(RAX, RSP, sourceDisplacement: 8); + //high + XS.Set(RDX, RSP, sourceDisplacement: 12); + + // pop both 8 byte values + XS.Add(RSP, 16); + + // set flags + XS.Or(RDI, RDI); + // if high dword of divisor is already zero, we dont need the loop + XS.Jump(ConditionalTestEnum.Zero, LabelNoLoop); + + // set ecx to zero for counting the shift operations + XS.Xor(RCX, RCX); + + XS.Label(LabelShiftRight); + + // shift divisor 1 bit right + XS.ShiftRightDouble(RSI, RDI, 1); + XS.ShiftRight(RDI, 1); + + // increment shift counter + XS.Increment(RCX); + + // set flags + XS.Or(RDI, RDI); + // loop while high dword of divisor till it is zero + XS.Jump(ConditionalTestEnum.NotZero, LabelShiftRight); + + // shift the dividend now in one step + XS.ShiftRightDouble(RAX, RDX, CL); + // shift dividend CL bits right + XS.ShiftRight(RDX, CL); + + // so we shifted both, so we have near the same relation as original values + // divide this + XS.Divide(RSI); + + // set eax to zero + XS.Xor(RAX, RAX); + + // shift the remainder in one step + XS.ShiftLeftDouble(RAX, RDX, CL); + // shift lower dword of remainder CL bits left + XS.ShiftLeft(RDX, CL); + + // save remainder to stack + XS.Push(RAX); + XS.Push(RDX); + + //TODO: implement proper derivation correction and overflow detection + + XS.Jump(LabelEnd); + + XS.Label(LabelNoLoop); + + //save high dividend + XS.Set(RCX, RAX); + XS.Set(RAX, RDX); + + // zero EDX, so that high part is zero -> reduce overflow case + XS.Xor(RDX, RDX); + + // divide high part + XS.Divide(RSI); + XS.Set(RAX, RCX); + + // divide low part + XS.Divide(RSI); + + // save remainder result + XS.Push(0); + XS.Push(RDX); + + XS.Label(LabelEnd); + } + else + { + XS.Pop(RCX); + + XS.Test(RCX, RCX); + XS.Jump(ConditionalTestEnum.NotZero, xNoDivideByZeroExceptionLabel); + + XS.Call(GetLabel(ExceptionHelperRefs.ThrowDivideByZeroExceptionRef)); + + XS.Label(xNoDivideByZeroExceptionLabel); + + XS.Pop(RAX); + + XS.Xor(RDX, RDX); + + XS.Divide(RCX); + XS.Push(RDX); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Rethrow.cs b/source/Cosmos.IL2CPU/IL/Rethrow.cs index 68d5947d3..deb354708 100644 --- a/source/Cosmos.IL2CPU/IL/Rethrow.cs +++ b/source/Cosmos.IL2CPU/IL/Rethrow.cs @@ -1,19 +1,19 @@ -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Rethrow)] - public class Rethrow : ILOp - { - public Rethrow(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - XS.Set(ECX, 3); - EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null); - } - } -} +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Rethrow)] + public class Rethrow : ILOp + { + public Rethrow(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + XS.Set(RCX, 3); + EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Shl.cs b/source/Cosmos.IL2CPU/IL/Shl.cs index c27faaa0d..29ff6b2fb 100644 --- a/source/Cosmos.IL2CPU/IL/Shl.cs +++ b/source/Cosmos.IL2CPU/IL/Shl.cs @@ -1,73 +1,73 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Shl )] - public class Shl : ILOp - { - public Shl( XSharp.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) - { - XS.Pop(XSRegisters.ECX); // shift amount - var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; - var xStackItem_Value = aOpCode.StackPopTypes[1]; - var xStackItem_Value_Size = SizeOfType(xStackItem_Value); -#if DOTNETCOMPATIBLE - if (xStackItem_Value.Size == 4) -#else - if (xStackItem_Value_Size <= 4) -#endif - { - XS.ShiftLeft(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - } -#if DOTNETCOMPATIBLE - else if (xStackItem_Value.Size == 8) -#else - else if (xStackItem_Value_Size <= 8) -#endif - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string LowPartIsZero = BaseLabel + "LowPartIsZero"; - string End_Shl = BaseLabel + "End_Shl"; - - // [ESP] is low part - // [ESP + 4] is high part - - // move low part to eax - XS.Set(EAX, ESP, sourceIsIndirect: true); - - XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); - XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero); - - // shift higher part - XS.ShiftLeftDouble(ESP, EAX, CL, destinationDisplacement: 4); - // shift lower part - // To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft! - XS.ShiftLeftArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - XS.Jump(End_Shl); - - XS.Label(LowPartIsZero); - // remove bits >= 32, so that CL max value could be only 31 - XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); - // shift low part in EAX and move it in high part - // To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft! - XS.ShiftLeftArithmetic(EAX, CL); - XS.Set(ESP, EAX, destinationDisplacement: 4); - // replace unknown low part with a zero, if <= 32 - XS.Set(XSRegisters.ESP, 0, destinationIsIndirect: true); - - XS.Label(End_Shl); - } - else - throw new NotSupportedException("A size bigger 8 not supported at Shl!"); - } - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Shl )] + public class Shl : ILOp + { + public Shl( XSharp.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) + { + XS.Pop(XSRegisters.RCX); // shift amount + var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; + var xStackItem_Value = aOpCode.StackPopTypes[1]; + var xStackItem_Value_Size = SizeOfType(xStackItem_Value); +#if DOTNETCOMPATIBLE + if (xStackItem_Value.Size == 4) +#else + if (xStackItem_Value_Size <= 4) +#endif + { + XS.ShiftLeft(XSRegisters.RSP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Long64); + } +#if DOTNETCOMPATIBLE + else if (xStackItem_Value.Size == 8) +#else + else if (xStackItem_Value_Size <= 8) +#endif + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string LowPartIsZero = BaseLabel + "LowPartIsZero"; + string End_Shl = BaseLabel + "End_Shl"; + + // [ESP] is low part + // [ESP + 4] is high part + + // move low part to eax + XS.Set(RAX, RSP, sourceIsIndirect: true); + + XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); + XS.Jump(CPUx86.ConditionalTestEnum.AboveOrEqual, LowPartIsZero); + + // shift higher part + XS.ShiftLeftDouble(RSP, RAX, CL, destinationDisplacement: 4); + // shift lower part + // To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft! + XS.ShiftLeftArithmetic(XSRegisters.RSP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Long64); + XS.Jump(End_Shl); + + XS.Label(LowPartIsZero); + // remove bits >= 32, so that CL max value could be only 31 + XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); + // shift low part in EAX and move it in high part + // To retain the sign bit we must use ShiftLeftArithmetic and not ShiftLeft! + XS.ShiftLeftArithmetic(RAX, CL); + XS.Set(RSP, RAX, destinationDisplacement: 4); + // replace unknown low part with a zero, if <= 32 + XS.Set(XSRegisters.RSP, 0, destinationIsIndirect: true); + + XS.Label(End_Shl); + } + else + throw new NotSupportedException("A size bigger 8 not supported at Shl!"); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Shr.cs b/source/Cosmos.IL2CPU/IL/Shr.cs index 65d734b7b..dad35a7f9 100644 --- a/source/Cosmos.IL2CPU/IL/Shr.cs +++ b/source/Cosmos.IL2CPU/IL/Shr.cs @@ -1,99 +1,99 @@ -using System; -using CPU = XSharp.Assembler.x86; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Shr )] - public class Shr : ILOp - { - public Shr( XSharp.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) - { - var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; - var xStackItem_Value = aOpCode.StackPopTypes[1]; - var xStackItem_Value_Size = SizeOfType(xStackItem_Value); - - XS.Pop(XSRegisters.ECX); // shift amount -#if DOTNETCOMPATIBLE - if (xStackItem_Value.Size == 4) -#else - if (xStackItem_Value_Size <= 4) -#endif - { - // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! - //XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - XS.ShiftRightArithmetic(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - } -#if DOTNETCOMPATIBLE - else if (xStackItem_Value_Size == 8) -#else - else if (xStackItem_Value_Size <= 8) -#endif - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string HighPartIsZero = BaseLabel + "HighPartIsZero"; - string End_Shr = BaseLabel + "End_Shr"; - - // [ESP] is low part - // [ESP + 4] is high part - - // move high part in EAX - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - - XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); - XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); - - // shift lower part - XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); - // shift higher part - // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! - //XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); - XS.ShiftRightArithmetic(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); - XS.Jump(End_Shr); - - XS.Label(HighPartIsZero); - - // remove bits >= 32, so that CL max value could be only 31 - XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); - - // shift high part and move it in low part - // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! - XS.ShiftRightArithmetic(XSRegisters.EAX, XSRegisters.CL); - XS.Set(ESP, EAX, destinationIsIndirect: true); - // replace unknown high part with a zero - XS.Set(ESP, 0, destinationIsIndirect: true, destinationDisplacement: 4); - //new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0}; - - XS.Label(End_Shr); - } - else - throw new NotSupportedException("A size bigger 8 not supported at Shr!"); - /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode); - var xStackItem_ShiftAmount = Assembler.Stack.Pop(); - var xStackItem_Value = Assembler.Stack.Peek(); - if( xStackItem_Value.Size <= 4 ) - { - XS.Pop(XSRegisters.ECX); // shift amount - XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true); - } - else if( xStackItem_Value.Size <= 8 ) - { - XS.Pop(XSRegisters.ECX); // shift amount - // [ESP] is high part - // [ESP + 4] is low part - XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - // shift low part - new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL }; - // shift high part - XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - }*/ - } - } -} +using System; +using CPU = XSharp.Assembler.x86; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Shr )] + public class Shr : ILOp + { + public Shr( XSharp.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) + { + var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; + var xStackItem_Value = aOpCode.StackPopTypes[1]; + var xStackItem_Value_Size = SizeOfType(xStackItem_Value); + + XS.Pop(XSRegisters.RCX); // shift amount +#if DOTNETCOMPATIBLE + if (xStackItem_Value.Size == 4) +#else + if (xStackItem_Value_Size <= 4) +#endif + { + // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! + //XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); + XS.ShiftRightArithmetic(XSRegisters.RSP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Long64); + } +#if DOTNETCOMPATIBLE + else if (xStackItem_Value_Size == 8) +#else + else if (xStackItem_Value_Size <= 8) +#endif + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string HighPartIsZero = BaseLabel + "HighPartIsZero"; + string End_Shr = BaseLabel + "End_Shr"; + + // [ESP] is low part + // [ESP + 4] is high part + + // move high part in EAX + XS.Set(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 4); + + XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); + XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); + + // shift lower part + XS.ShiftRightDouble(RSP, RAX, CL, destinationIsIndirect: true); + // shift higher part + // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! + //XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); + XS.ShiftRightArithmetic(RSP, CL, destinationDisplacement: 4, size: RegisterSize.Long64); + XS.Jump(End_Shr); + + XS.Label(HighPartIsZero); + + // remove bits >= 32, so that CL max value could be only 31 + XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); + + // shift high part and move it in low part + // To retain the sign bit we must use ShiftRightArithmetic and not ShiftRight! + XS.ShiftRightArithmetic(XSRegisters.RAX, XSRegisters.CL); + XS.Set(RSP, RAX, destinationIsIndirect: true); + // replace unknown high part with a zero + XS.Set(RSP, 0, destinationIsIndirect: true, destinationDisplacement: 4); + //new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0}; + + XS.Label(End_Shr); + } + else + throw new NotSupportedException("A size bigger 8 not supported at Shr!"); + /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode); + var xStackItem_ShiftAmount = Assembler.Stack.Pop(); + var xStackItem_Value = Assembler.Stack.Peek(); + if( xStackItem_Value.Size <= 4 ) + { + XS.Pop(XSRegisters.ECX); // shift amount + XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true); + } + else if( xStackItem_Value.Size <= 8 ) + { + XS.Pop(XSRegisters.ECX); // shift amount + // [ESP] is high part + // [ESP + 4] is low part + XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); + // shift low part + new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL }; + // shift high part + XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); + }*/ + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Shr_Un.cs b/source/Cosmos.IL2CPU/IL/Shr_Un.cs index 171db53b9..9187bbf86 100644 --- a/source/Cosmos.IL2CPU/IL/Shr_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Shr_Un.cs @@ -1,167 +1,167 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; -using CPU = XSharp.Assembler.x86; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Shr_Un )] - public class Shr_Un : ILOp - { - public Shr_Un( XSharp.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) - { - var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; - var xStackItem_Value = aOpCode.StackPopTypes[1]; - var xStackItem_Value_Size = SizeOfType(xStackItem_Value); - - XS.Pop(XSRegisters.ECX); // shift amount -#if DOTNETCOMPATIBLE - if (xStackItem_Value.Size == 4) -#else - if (xStackItem_Value_Size <= 4) -#endif - { - XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - } -#if DOTNETCOMPATIBLE - else if (xStackItem_Value_Size == 8) -#else - else if (xStackItem_Value_Size <= 8) -#endif - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string HighPartIsZero = BaseLabel + "HighPartIsZero"; - string End_Shr = BaseLabel + "End_Shr"; - - // [ESP] is low part - // [ESP + 4] is high part - - // move high part in EAX - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - - XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); - XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); - - // shift lower part - XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); - // shift higher part - XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); - XS.Jump(End_Shr); - - XS.Label(HighPartIsZero); - // remove bits >= 32, so that CL max value could be only 31 - XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); - - // shift high part and move it in low part - XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL); - XS.Set(ESP, EAX, destinationIsIndirect: true); - // replace unknown high part with a zero - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0}; - - XS.Label(End_Shr); - } - else - throw new NotSupportedException("A size bigger 8 not supported at Shr!"); - /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode); - var xStackItem_ShiftAmount = Assembler.Stack.Pop(); - var xStackItem_Value = Assembler.Stack.Peek(); - if( xStackItem_Value.Size <= 4 ) - { - XS.Pop(XSRegisters.ECX); // shift amount - XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true); - } - else if( xStackItem_Value.Size <= 8 ) - { - XS.Pop(XSRegisters.ECX); // shift amount - // [ESP] is high part - // [ESP + 4] is low part - XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - // shift low part - new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL }; - // shift high part - XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); - }*/ - -#if false - XS.Pop(XSRegisters.ECX); // shift amount - string xBaseLabel = GetLabel( aMethod, aOpCode ) + "."; - var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; - var xStackItem_Value = aOpCode.StackPopTypes[1]; - - if (TypeIsFloat(xStackItem_Value)) - { - throw new NotImplementedException("Floats not yet supported!"); - } - var xStackItem_Value_Size = SizeOfType(xStackItem_Value); - if( xStackItem_Value_Size <= 4 ) - { - XS.Pop(XSRegisters.EAX); // shift amount - XS.Pop(XSRegisters.EBX); // value - XS.Set(XSRegisters.CL, XSRegisters.AL); - XS.ShiftRight(XSRegisters.EBX, CL); - XS.Push(XSRegisters.EBX); - return; - } - if( xStackItem_Value_Size <= 8 ) - { - string BaseLabel = GetLabel(aMethod, aOpCode) + "."; - string HighPartIsZero = BaseLabel + "HighPartIsZero"; - string End_Shr = BaseLabel + "End_Shr"; - - // [ESP] is low part - // [ESP + 4] is high part - - // move high part in EAX - XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); - - XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); - XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); - - // shift lower part - XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); - // shift higher part - XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); - XS.Jump(End_Shr); - - XS.Label(HighPartIsZero); - // remove bits >= 32, so that CL max value could be only 31 - XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); - - // shift high part and move it in low part - XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL); - XS.Set(ESP, EAX, destinationIsIndirect: true); - // replace unknown high part with a zero, if <= 32 - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0 }; - - XS.Label(End_Shr); - -#if false - XS.Pop(XSRegisters.EDX); - XS.Set(XSRegisters.EAX, 0); - XS.Label(xBaseLabel + "__StartLoop" ); - XS.Compare(XSRegisters.EDX, XSRegisters.EAX); - XS.Jump(CPUx86.ConditionalTestEnum.Equal, xBaseLabel + "__EndLoop"); - XS.Set(EBX, ESP, sourceIsIndirect: true); - XS.Set(XSRegisters.CL, 1); - XS.ShiftRight(XSRegisters.EBX, CL); - XS.Set(ESP, EBX, destinationIsIndirect: true); - XS.Set(XSRegisters.CL, 1); - XS.RotateThroughCarryRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); - XS.Add(XSRegisters.EAX, 1); - new CPUx86.Jump { DestinationLabel = xBaseLabel + "__StartLoop" }; - - - XS.Label(xBaseLabel + "__EndLoop" ); -#endif - return; -#endif - } - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; +using CPU = XSharp.Assembler.x86; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Shr_Un )] + public class Shr_Un : ILOp + { + public Shr_Un( XSharp.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode ) + { + var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; + var xStackItem_Value = aOpCode.StackPopTypes[1]; + var xStackItem_Value_Size = SizeOfType(xStackItem_Value); + + XS.Pop(XSRegisters.RCX); // shift amount +#if DOTNETCOMPATIBLE + if (xStackItem_Value.Size == 4) +#else + if (xStackItem_Value_Size <= 4) +#endif + { + XS.ShiftRight(XSRegisters.RSP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Long64); + } +#if DOTNETCOMPATIBLE + else if (xStackItem_Value_Size == 8) +#else + else if (xStackItem_Value_Size <= 8) +#endif + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string HighPartIsZero = BaseLabel + "HighPartIsZero"; + string End_Shr = BaseLabel + "End_Shr"; + + // [ESP] is low part + // [ESP + 4] is high part + + // move high part in EAX + XS.Set(XSRegisters.RAX, XSRegisters.RSP, sourceDisplacement: 4); + + XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); + XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); + + // shift lower part + XS.ShiftRightDouble(RSP, RAX, CL, destinationIsIndirect: true); + // shift higher part + XS.ShiftRight(RSP, CL, destinationDisplacement: 4, size: RegisterSize.Long64); + XS.Jump(End_Shr); + + XS.Label(HighPartIsZero); + // remove bits >= 32, so that CL max value could be only 31 + XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); + + // shift high part and move it in low part + XS.ShiftRight(XSRegisters.RAX, XSRegisters.CL); + XS.Set(RSP, RAX, destinationIsIndirect: true); + // replace unknown high part with a zero + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0}; + + XS.Label(End_Shr); + } + else + throw new NotSupportedException("A size bigger 8 not supported at Shr!"); + /*string xLabelName = AppAssembler.TmpPosLabel(aMethod, aOpCode); + var xStackItem_ShiftAmount = Assembler.Stack.Pop(); + var xStackItem_Value = Assembler.Stack.Peek(); + if( xStackItem_Value.Size <= 4 ) + { + XS.Pop(XSRegisters.ECX); // shift amount + XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true); + } + else if( xStackItem_Value.Size <= 8 ) + { + XS.Pop(XSRegisters.ECX); // shift amount + // [ESP] is high part + // [ESP + 4] is low part + XS.Mov(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); + // shift low part + new CPUx86.ShiftRightDouble { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, SourceReg = CPUx86.Registers.EAX, ArgumentReg = CPUx86.Registers.CL }; + // shift high part + XS.ShiftRight(XSRegisters.ESP, XSRegisters.CL, destinationIsIndirect: true, size: RegisterSize.Int32); + }*/ + +#if false + XS.Pop(XSRegisters.ECX); // shift amount + string xBaseLabel = GetLabel( aMethod, aOpCode ) + "."; + var xStackItem_ShiftAmount = aOpCode.StackPopTypes[0]; + var xStackItem_Value = aOpCode.StackPopTypes[1]; + + if (TypeIsFloat(xStackItem_Value)) + { + throw new NotImplementedException("Floats not yet supported!"); + } + var xStackItem_Value_Size = SizeOfType(xStackItem_Value); + if( xStackItem_Value_Size <= 4 ) + { + XS.Pop(XSRegisters.EAX); // shift amount + XS.Pop(XSRegisters.EBX); // value + XS.Set(XSRegisters.CL, XSRegisters.AL); + XS.ShiftRight(XSRegisters.EBX, CL); + XS.Push(XSRegisters.EBX); + return; + } + if( xStackItem_Value_Size <= 8 ) + { + string BaseLabel = GetLabel(aMethod, aOpCode) + "."; + string HighPartIsZero = BaseLabel + "HighPartIsZero"; + string End_Shr = BaseLabel + "End_Shr"; + + // [ESP] is low part + // [ESP + 4] is high part + + // move high part in EAX + XS.Set(XSRegisters.EAX, XSRegisters.ESP, sourceDisplacement: 4); + + XS.Compare(XSRegisters.CL, 32, size: RegisterSize.Byte8); + XS.Jump(CPU.ConditionalTestEnum.AboveOrEqual, HighPartIsZero); + + // shift lower part + XS.ShiftRightDouble(ESP, EAX, CL, destinationIsIndirect: true); + // shift higher part + XS.ShiftRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); + XS.Jump(End_Shr); + + XS.Label(HighPartIsZero); + // remove bits >= 32, so that CL max value could be only 31 + XS.And(XSRegisters.CL, 0x1f, size: RegisterSize.Byte8); + + // shift high part and move it in low part + XS.ShiftRight(XSRegisters.EAX, XSRegisters.CL); + XS.Set(ESP, EAX, destinationIsIndirect: true); + // replace unknown high part with a zero, if <= 32 + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ESP, DestinationIsIndirect = true, DestinationDisplacement = 4, SourceValue = 0 }; + + XS.Label(End_Shr); + +#if false + XS.Pop(XSRegisters.EDX); + XS.Set(XSRegisters.EAX, 0); + XS.Label(xBaseLabel + "__StartLoop" ); + XS.Compare(XSRegisters.EDX, XSRegisters.EAX); + XS.Jump(CPUx86.ConditionalTestEnum.Equal, xBaseLabel + "__EndLoop"); + XS.Set(EBX, ESP, sourceIsIndirect: true); + XS.Set(XSRegisters.CL, 1); + XS.ShiftRight(XSRegisters.EBX, CL); + XS.Set(ESP, EBX, destinationIsIndirect: true); + XS.Set(XSRegisters.CL, 1); + XS.RotateThroughCarryRight(ESP, CL, destinationDisplacement: 4, size: RegisterSize.Int32); + XS.Add(XSRegisters.EAX, 1); + new CPUx86.Jump { DestinationLabel = xBaseLabel + "__StartLoop" }; + + + XS.Label(xBaseLabel + "__EndLoop" ); +#endif + return; +#endif + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Starg.cs b/source/Cosmos.IL2CPU/IL/Starg.cs index ab52cd4a6..3ddf59062 100644 --- a/source/Cosmos.IL2CPU/IL/Starg.cs +++ b/source/Cosmos.IL2CPU/IL/Starg.cs @@ -1,59 +1,59 @@ -using Cosmos.IL2CPU.ILOpCodes; -using System; -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Starg)] - public class Starg : ILOp - { - public Starg(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpVar = (OpVar)aOpCode; - DoExecute(Assembler, aMethod, xOpVar.Value); - } - - public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, ushort aParam) - { - var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, aParam); - Type xArgType; - if (aMethod.MethodBase.IsStatic) - { - xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; - } - else - { - if (aParam == 0u) - { - xArgType = aMethod.MethodBase.DeclaringType; - if (xArgType.IsValueType) - { - xArgType = xArgType.MakeByRefType(); - } - } - else - { - xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; - } - } - - XS.Comment("Arg idx = " + aParam); - uint xArgRealSize = SizeOfType(xArgType); - uint xArgSize = Align(xArgRealSize, 4); - XS.Comment("Arg type = " + xArgType); - XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); - - for (int i = (int)(xArgSize / 4) - 1; i >= 0; i--) - { - XS.Pop(EAX); - XS.Set(EBP, EAX, destinationIsIndirect: true, destinationDisplacement: xDisplacement - i * 4); - } - } - } -} +using Cosmos.IL2CPU.ILOpCodes; +using System; +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Starg)] + public class Starg : ILOp + { + public Starg(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpVar = (OpVar)aOpCode; + DoExecute(Assembler, aMethod, xOpVar.Value); + } + + public static void DoExecute(XSharp.Assembler.Assembler Assembler, Il2cpuMethodInfo aMethod, ushort aParam) + { + var xDisplacement = Ldarg.GetArgumentDisplacement(aMethod, aParam); + Type xArgType; + if (aMethod.MethodBase.IsStatic) + { + xArgType = aMethod.MethodBase.GetParameters()[aParam].ParameterType; + } + else + { + if (aParam == 0u) + { + xArgType = aMethod.MethodBase.DeclaringType; + if (xArgType.IsValueType) + { + xArgType = xArgType.MakeByRefType(); + } + } + else + { + xArgType = aMethod.MethodBase.GetParameters()[aParam - 1].ParameterType; + } + } + + XS.Comment("Arg idx = " + aParam); + uint xArgRealSize = SizeOfType(xArgType); + uint xArgSize = Align(xArgRealSize, 4); + XS.Comment("Arg type = " + xArgType); + XS.Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); + + for (int i = (int)(xArgSize / 4) - 1; i >= 0; i--) + { + XS.Pop(RAX); + XS.Set(RBP, RAX, destinationIsIndirect: true, destinationDisplacement: xDisplacement - i * 4); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs b/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs index 4ee074723..bed29a4d7 100644 --- a/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs +++ b/source/Cosmos.IL2CPU/IL/Stelem_Ref.cs @@ -1,108 +1,108 @@ -using System; -using Cosmos.Debug.Kernel; -using IL2CPU.API; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; -using CPUx86 = XSharp.Assembler.x86; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Stelem_Ref)] - public class Stelem_Ref : ILOp - { - public Stelem_Ref(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public static void Assemble(Assembler aAssembler, uint aElementSize, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) - { - DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4))); - uint xStackSize = aElementSize; - if (xStackSize % 4 != 0) - { - xStackSize += 4 - xStackSize % 4; - } - // Do index out of range check - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; - var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; - XS.Push(ESP, displacement: 4 + 4 + (int)xStackSize); // _, array, 0, index, value * n => _, array, 0, index, value * n, array - XS.Push(0); // _, array, 0, index, value * n, array => _, array, 0, index, value * n, array, 0 - Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, index, value * n, array, 0 -> _, array, 0, index, value * n, length - XS.Pop(EAX); //Length of array _, array, 0, index, value * n, length -> _, array, 0, index, value * n - XS.Compare(EAX, ESP, sourceIsIndirect: true, sourceDisplacement: (int)xStackSize); - XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); - - XS.Compare(EAX, 0); - XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); - - XS.Label(xIndexOutOfRangeExeptionLabel); - XS.Exchange(BX, BX); - Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); - - XS.Label(xNoIndexOutOfRangeExeptionLabel); - - // calculate element offset into array memory (including header) - XS.Set(EAX, ESP, sourceDisplacement: (int)xStackSize); // the index - XS.Set(EDX, aElementSize); - XS.Multiply(EDX); - XS.Add(EAX, ObjectUtils.FieldDataOffset + 4); - - XS.Set(EDX, ESP, sourceDisplacement: (int)xStackSize + 8); // the array - XS.Add(EDX, EAX); - XS.Push(EDX); - - XS.Pop(ECX); - - //get bytes - var bytes = aElementSize / 4; - for (uint i = bytes; i > 0; i -= 1) - { - new Comment(aAssembler, "Start 1 dword"); - XS.Pop(EBX); - XS.Set(ECX, EBX, destinationIsIndirect: true); - XS.Add(ECX, 4); - } - switch (aElementSize % 4) - { - case 1: - { - new Comment(aAssembler, "Start 1 byte"); - XS.Pop(EBX); - XS.Set(ECX, BL, destinationIsIndirect: true); - break; - } - case 2: - { - new Comment(aAssembler, "Start 1 word"); - XS.Pop(EBX); - XS.Set(ECX, BX, destinationIsIndirect: true); - break; - } - case 3: - { - new Comment(aAssembler, "Start 3 word"); - XS.Pop(EBX); - XS.And(EBX, 0xFFFFFF); // Only take the value of the lower three bytes - XS.Set(ECX, EBX, destinationIsIndirect: true); - break; - } - case 0: - { - break; - } - default: - throw new Exception("Remainder size " + aElementSize % 4 + " not supported!"); - - } - - XS.Add(ESP, 12); - } - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - Assemble(Assembler, 8, aMethod, aOpCode, DebugEnabled); - } - } -} +using System; +using Cosmos.Debug.Kernel; +using IL2CPU.API; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; +using CPUx86 = XSharp.Assembler.x86; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Stelem_Ref)] + public class Stelem_Ref : ILOp + { + public Stelem_Ref(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public static void Assemble(Assembler aAssembler, uint aElementSize, Il2cpuMethodInfo aMethod, ILOpCode aOpCode, bool debugEnabled) + { + DoNullReferenceCheck(aAssembler, debugEnabled, (int)(8 + Align(aElementSize, 4))); + uint xStackSize = aElementSize; + if (xStackSize % 4 != 0) + { + xStackSize += 4 - xStackSize % 4; + } + // Do index out of range check + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xNoIndexOutOfRangeExeptionLabel = xBaseLabel + "_NoIndexOutOfRangeException"; + var xIndexOutOfRangeExeptionLabel = xBaseLabel + "_IndexOutOfRangeException"; + XS.Push(RSP, displacement: 4 + 4 + (int)xStackSize); // _, array, 0, index, value * n => _, array, 0, index, value * n, array + XS.Push(0); // _, array, 0, index, value * n, array => _, array, 0, index, value * n, array, 0 + Ldlen.Assemble(aAssembler, debugEnabled, false); // _, array, 0, index, value * n, array, 0 -> _, array, 0, index, value * n, length + XS.Pop(RAX); //Length of array _, array, 0, index, value * n, length -> _, array, 0, index, value * n + XS.Compare(RAX, RSP, sourceIsIndirect: true, sourceDisplacement: (int)xStackSize); + XS.Jump(CPUx86.ConditionalTestEnum.LessThanOrEqualTo, xIndexOutOfRangeExeptionLabel); + + XS.Compare(RAX, 0); + XS.Jump(CPUx86.ConditionalTestEnum.GreaterThanOrEqualTo, xNoIndexOutOfRangeExeptionLabel); + + XS.Label(xIndexOutOfRangeExeptionLabel); + XS.Exchange(BX, BX); + Call.DoExecute(aAssembler, aMethod, ExceptionHelperRefs.ThrowIndexOutOfRangeException, aOpCode, xNoIndexOutOfRangeExeptionLabel, debugEnabled); + + XS.Label(xNoIndexOutOfRangeExeptionLabel); + + // calculate element offset into array memory (including header) + XS.Set(RAX, RSP, sourceDisplacement: (int)xStackSize); // the index + XS.Set(RDX, aElementSize); + XS.Multiply(RDX); + XS.Add(RAX, ObjectUtils.FieldDataOffset + 4); + + XS.Set(RDX, RSP, sourceDisplacement: (int)xStackSize + 8); // the array + XS.Add(RDX, RAX); + XS.Push(RDX); + + XS.Pop(RCX); + + //get bytes + var bytes = aElementSize / 4; + for (uint i = bytes; i > 0; i -= 1) + { + new Comment(aAssembler, "Start 1 dword"); + XS.Pop(RBX); + XS.Set(RCX, RBX, destinationIsIndirect: true); + XS.Add(RCX, 4); + } + switch (aElementSize % 4) + { + case 1: + { + new Comment(aAssembler, "Start 1 byte"); + XS.Pop(RBX); + XS.Set(RCX, BL, destinationIsIndirect: true); + break; + } + case 2: + { + new Comment(aAssembler, "Start 1 word"); + XS.Pop(RBX); + XS.Set(RCX, BX, destinationIsIndirect: true); + break; + } + case 3: + { + new Comment(aAssembler, "Start 3 word"); + XS.Pop(RBX); + XS.And(RBX, 0xFFFFFF); // Only take the value of the lower three bytes + XS.Set(RCX, RBX, destinationIsIndirect: true); + break; + } + case 0: + { + break; + } + default: + throw new Exception("Remainder size " + aElementSize % 4 + " not supported!"); + + } + + XS.Add(RSP, 12); + } + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + Assemble(Assembler, 8, aMethod, aOpCode, DebugEnabled); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Stfld.cs b/source/Cosmos.IL2CPU/IL/Stfld.cs index ff053ba50..0ab61e28a 100644 --- a/source/Cosmos.IL2CPU/IL/Stfld.cs +++ b/source/Cosmos.IL2CPU/IL/Stfld.cs @@ -1,117 +1,117 @@ -using System; -using System.Reflection; -using Cosmos.IL2CPU.Extensions; -using XSharp; -using CPUx86 = XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Stfld)] - public class Stfld : ILOp - { - public Stfld(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpCode = (ILOpCodes.OpField)aOpCode; - var xField = xOpCode.Value; - XS.Comment("Operand type: " + aOpCode.StackPopTypes[1].ToString()); - DoExecute(Assembler, aMethod, xField, DebugEnabled, IsReferenceType(aOpCode.StackPopTypes[1])); - } - - public static void DoExecute(XSharp.Assembler.Assembler aAssembler, Il2cpuMethodInfo aMethod, string aFieldId, Type aDeclaringObject, bool aNeedsGC, bool debugEnabled) - { - var xFieldInfo = ResolveField(aDeclaringObject, aFieldId, true); - var xActualOffset = Ldfld.GetFieldOffset(aDeclaringObject, aFieldId); - var xSize = xFieldInfo.Size; - XS.Comment("DeclaringObject: " + aDeclaringObject.Name); - XS.Comment("Field: " + xFieldInfo.Id); - var fieldType = xFieldInfo.FieldType; - XS.Comment("Type: " + fieldType.ToString()); - XS.Comment("Size: " + xFieldInfo.Size); - XS.Comment("Offset: " + xActualOffset + " (includes object header)"); - - uint xRoundedSize = Align(xSize, 4); - if (aNeedsGC) - { - DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize + 4); - } - else - { - DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize); - } - - XS.Comment("After Nullref check"); - - // Determine field in obejct position - if (aNeedsGC) - { - XS.Set(ECX, ESP, sourceDisplacement: (int)xRoundedSize + 4); - } - else - { - XS.Set(ECX, ESP, sourceDisplacement: (int)xRoundedSize); - } - - if (xActualOffset != 0) - { - XS.Add(ECX, (uint)xActualOffset); - } - - //TODO: Can't we use an x86 op to do a byte copy instead and be faster? - for (int i = 0; i < xSize / 4; i++) - { - XS.Pop(EAX); - XS.Set(ECX, EAX, destinationDisplacement: (int)(i * 4)); - } - - switch (xSize % 4) - { - case 1: - { - XS.Pop(EAX); - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4), SourceReg = CPUx86.RegistersEnum.AL }; - break; - } - case 2: - { - XS.Pop(EAX); - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4), SourceReg = CPUx86.RegistersEnum.AX }; - break; - } - case 3: - { - XS.Pop(EAX); - // move 2 lower bytes - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4), SourceReg = CPUx86.RegistersEnum.AX }; - // shift third byte to lowest - XS.ShiftRight(EAX, 16); - new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4) + 2, SourceReg = CPUx86.RegistersEnum.AL }; - break; - } - case 0: - { - break; - } - default: - throw new Exception("Remainder size " + xSize % 4 + " not supported!"); - } - - // remove object from stack - XS.Add(ESP, 4); - if (aNeedsGC) - { - XS.Add(ESP, 4); - } - } - - public static void DoExecute(XSharp.Assembler.Assembler aAssembler, Il2cpuMethodInfo aMethod, FieldInfo aField, bool debugEnabled, bool aNeedsGC) - { - DoExecute(aAssembler, aMethod, aField.GetFullName(), aField.DeclaringType, aNeedsGC, debugEnabled); - } - - } -} +using System; +using System.Reflection; +using Cosmos.IL2CPU.Extensions; +using XSharp; +using CPUx86 = XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Stfld)] + public class Stfld : ILOp + { + public Stfld(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpCode = (ILOpCodes.OpField)aOpCode; + var xField = xOpCode.Value; + XS.Comment("Operand type: " + aOpCode.StackPopTypes[1].ToString()); + DoExecute(Assembler, aMethod, xField, DebugEnabled, IsReferenceType(aOpCode.StackPopTypes[1])); + } + + public static void DoExecute(XSharp.Assembler.Assembler aAssembler, Il2cpuMethodInfo aMethod, string aFieldId, Type aDeclaringObject, bool aNeedsGC, bool debugEnabled) + { + var xFieldInfo = ResolveField(aDeclaringObject, aFieldId, true); + var xActualOffset = Ldfld.GetFieldOffset(aDeclaringObject, aFieldId); + var xSize = xFieldInfo.Size; + XS.Comment("DeclaringObject: " + aDeclaringObject.Name); + XS.Comment("Field: " + xFieldInfo.Id); + var fieldType = xFieldInfo.FieldType; + XS.Comment("Type: " + fieldType.ToString()); + XS.Comment("Size: " + xFieldInfo.Size); + XS.Comment("Offset: " + xActualOffset + " (includes object header)"); + + uint xRoundedSize = Align(xSize, 4); + if (aNeedsGC) + { + DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize + 4); + } + else + { + DoNullReferenceCheck(aAssembler, debugEnabled, (int)xRoundedSize); + } + + XS.Comment("After Nullref check"); + + // Determine field in obejct position + if (aNeedsGC) + { + XS.Set(RCX, RSP, sourceDisplacement: (int)xRoundedSize + 4); + } + else + { + XS.Set(RCX, RSP, sourceDisplacement: (int)xRoundedSize); + } + + if (xActualOffset != 0) + { + XS.Add(RCX, (uint)xActualOffset); + } + + //TODO: Can't we use an x86 op to do a byte copy instead and be faster? + for (int i = 0; i < xSize / 4; i++) + { + XS.Pop(RAX); + XS.Set(RCX, RAX, destinationDisplacement: (int)(i * 4)); + } + + switch (xSize % 4) + { + case 1: + { + XS.Pop(RAX); + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4), SourceReg = CPUx86.RegistersEnum.AL }; + break; + } + case 2: + { + XS.Pop(RAX); + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4), SourceReg = CPUx86.RegistersEnum.AX }; + break; + } + case 3: + { + XS.Pop(RAX); + // move 2 lower bytes + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4), SourceReg = CPUx86.RegistersEnum.AX }; + // shift third byte to lowest + XS.ShiftRight(RAX, 16); + new CPUx86.Mov { DestinationReg = CPUx86.RegistersEnum.ECX, DestinationIsIndirect = true, DestinationDisplacement = (int)(xSize / 4 * 4) + 2, SourceReg = CPUx86.RegistersEnum.AL }; + break; + } + case 0: + { + break; + } + default: + throw new Exception("Remainder size " + xSize % 4 + " not supported!"); + } + + // remove object from stack + XS.Add(RSP, 4); + if (aNeedsGC) + { + XS.Add(RSP, 4); + } + } + + public static void DoExecute(XSharp.Assembler.Assembler aAssembler, Il2cpuMethodInfo aMethod, FieldInfo aField, bool debugEnabled, bool aNeedsGC) + { + DoExecute(aAssembler, aMethod, aField.GetFullName(), aField.DeclaringType, aNeedsGC, debugEnabled); + } + + } +} diff --git a/source/Cosmos.IL2CPU/IL/Stind.cs b/source/Cosmos.IL2CPU/IL/Stind.cs index 2f821637d..39354e559 100644 --- a/source/Cosmos.IL2CPU/IL/Stind.cs +++ b/source/Cosmos.IL2CPU/IL/Stind.cs @@ -34,30 +34,30 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) switch (aOpCode.OpCode) { case ILOpCode.Code.Stind_I1: - XS.Pop(ECX); - XS.Pop(EAX); - XS.Set(EAX, CL, destinationIsIndirect: true); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Set(RAX, CL, destinationIsIndirect: true); break; case ILOpCode.Code.Stind_I2: - XS.Pop(ECX); - XS.Pop(EAX); - XS.Set(EAX, CX, destinationIsIndirect: true); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Set(RAX, CX, destinationIsIndirect: true); break; case ILOpCode.Code.Stind_I: case ILOpCode.Code.Stind_I4: case ILOpCode.Code.Stind_R4: - XS.Pop(ECX); - XS.Pop(EAX); - XS.Set(EAX, ECX, destinationIsIndirect: true); + XS.Pop(RCX); + XS.Pop(RAX); + XS.Set(RAX, RCX, destinationIsIndirect: true); break; case ILOpCode.Code.Stind_I8: case ILOpCode.Code.Stind_R8: case ILOpCode.Code.Stind_Ref: - XS.Pop(ECX); - XS.Pop(EBX); - XS.Pop(EAX); - XS.Set(EAX, ECX, destinationIsIndirect: true); - XS.Set(EAX, EBX, destinationDisplacement: 4); + XS.Pop(RCX); + XS.Pop(RBX); + XS.Pop(RAX); + XS.Set(RAX, RCX, destinationIsIndirect: true); + XS.Set(RAX, RBX, destinationDisplacement: 4); break; } } diff --git a/source/Cosmos.IL2CPU/IL/Stloc.cs b/source/Cosmos.IL2CPU/IL/Stloc.cs index b5c003fca..91b716ea3 100644 --- a/source/Cosmos.IL2CPU/IL/Stloc.cs +++ b/source/Cosmos.IL2CPU/IL/Stloc.cs @@ -1,39 +1,39 @@ -using System; -using Cosmos.IL2CPU.Extensions; -using Cosmos.IL2CPU.ILOpCodes; -using IL2CPU.API; -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; -using CPU = XSharp.Assembler.x86; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Stloc)] - public class Stloc : ILOp - { - public Stloc(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xOpVar = (OpVar)aOpCode; - var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; - var xStackCount = (int)GetStackCountForLocal(aMethod, xVar.LocalType); - var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); - var xSize = SizeOfType(xVar.LocalType); - - XS.Comment("Local type = " + xVar.LocalType); - XS.Comment("Local EBP offset = " + xEBPOffset); - XS.Comment("Local size = " + xSize); - - for (int i = xStackCount - 1; i >= 0; i--) - { - XS.Pop(EAX); - XS.Set(EBP, EAX, destinationDisplacement: 0 - (xEBPOffset + i * 4)); - } - } - } -} +using System; +using Cosmos.IL2CPU.Extensions; +using Cosmos.IL2CPU.ILOpCodes; +using IL2CPU.API; +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; +using CPU = XSharp.Assembler.x86; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Stloc)] + public class Stloc : ILOp + { + public Stloc(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xOpVar = (OpVar)aOpCode; + var xVar = aMethod.MethodBase.GetLocalVariables()[xOpVar.Value]; + var xStackCount = (int)GetStackCountForLocal(aMethod, xVar.LocalType); + var xEBPOffset = (int)GetEBPOffsetForLocal(aMethod, xOpVar.Value); + var xSize = SizeOfType(xVar.LocalType); + + XS.Comment("Local type = " + xVar.LocalType); + XS.Comment("Local EBP offset = " + xEBPOffset); + XS.Comment("Local size = " + xSize); + + for (int i = xStackCount - 1; i >= 0; i--) + { + XS.Pop(RAX); + XS.Set(RBP, RAX, destinationDisplacement: 0 - (xEBPOffset + i * 4)); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Stobj.cs b/source/Cosmos.IL2CPU/IL/Stobj.cs index 5901f7a0e..e98ad1132 100644 --- a/source/Cosmos.IL2CPU/IL/Stobj.cs +++ b/source/Cosmos.IL2CPU/IL/Stobj.cs @@ -1,56 +1,56 @@ -using System; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Stobj)] - public class Stobj : ILOp - { - public Stobj(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xFieldSize = SizeOfType(aOpCode.StackPopTypes[0]); - var xRoundedSize = Align(xFieldSize, 4); - DoNullReferenceCheck(Assembler, DebugEnabled, (int)xRoundedSize); - - XS.Set(ECX, ESP, sourceDisplacement: checked((int)xRoundedSize)); - - for (int i = 0; i < xFieldSize / 4; i++) - { - XS.Pop(EAX); - XS.Set(ECX, EAX, destinationDisplacement: i * 4); - } - - switch (xFieldSize % 4) - { - case 1: - { - XS.Pop(EAX); - XS.Set(ECX, AL, destinationDisplacement: checked((int)(xFieldSize / 4) * 4)); - break; - } - case 2: - { - XS.Pop(EAX); - XS.Set(ECX, AX, destinationDisplacement: checked((int)(xFieldSize / 4) * 4)); - break; - } - case 0: - { - break; - } - default: - throw new Exception("Remainder size " + xFieldSize % 4 + " not supported!"); - } - - XS.Add(ESP, 4); - } - } -} +using System; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Stobj)] + public class Stobj : ILOp + { + public Stobj(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xFieldSize = SizeOfType(aOpCode.StackPopTypes[0]); + var xRoundedSize = Align(xFieldSize, 4); + DoNullReferenceCheck(Assembler, DebugEnabled, (int)xRoundedSize); + + XS.Set(RCX, RSP, sourceDisplacement: checked((int)xRoundedSize)); + + for (int i = 0; i < xFieldSize / 4; i++) + { + XS.Pop(RAX); + XS.Set(RCX, RAX, destinationDisplacement: i * 4); + } + + switch (xFieldSize % 4) + { + case 1: + { + XS.Pop(RAX); + XS.Set(RCX, AL, destinationDisplacement: checked((int)(xFieldSize / 4) * 4)); + break; + } + case 2: + { + XS.Pop(RAX); + XS.Set(RCX, AX, destinationDisplacement: checked((int)(xFieldSize / 4) * 4)); + break; + } + case 0: + { + break; + } + default: + throw new Exception("Remainder size " + xFieldSize % 4 + " not supported!"); + } + + XS.Add(RSP, 4); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Stsfld.cs b/source/Cosmos.IL2CPU/IL/Stsfld.cs index 262f956e9..499f08f0b 100644 --- a/source/Cosmos.IL2CPU/IL/Stsfld.cs +++ b/source/Cosmos.IL2CPU/IL/Stsfld.cs @@ -1,129 +1,129 @@ -using System; -using System.Linq; -using System.Reflection; - -using IL2CPU.API; - -using XSharp; -using XSharp.Assembler; -using CPU = XSharp.Assembler.x86; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Stsfld)] - public class Stsfld : ILOp - { - public Stsfld(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aMethod.MethodBase.DeclaringType; - var xOpCode = (ILOpCodes.OpField)aOpCode; - FieldInfo xField = xOpCode.Value; - var xIsReferenceType = IsReferenceType(xField.FieldType); - - // call cctor: - var xCctor = xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic).SingleOrDefault(); - if (xCctor != null) - { - XS.Call(LabelName.Get(xCctor)); - EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck"); - XS.Label(".AfterCCTorExceptionCheck"); - } - - uint xSize = SizeOfType(xField.FieldType); - - XS.Comment("Type = '" + xField.FieldType.FullName + "'"); - uint xOffset = 0; - - var xFields = xField.DeclaringType.GetFields(); - - foreach (FieldInfo xInfo in xFields) - { - if (xInfo == xField) - { - break; - } - - xOffset += SizeOfType(xInfo.FieldType); - } - string xDataName = LabelName.GetStaticFieldName(xField); - - if (xIsReferenceType) - { - var name = ElementReference.New(xDataName).Name; - XS.Add(ESP, 4); - - // GC clean up old object - XS.Compare(name, 0, destinationIsIndirect: true, destinationDisplacement: 4); - XS.Jump(CPU.ConditionalTestEnum.Equal, ".AfterGC"); - XS.Push(name, isIndirect: true, displacement: 4); // push object as pointer to send to DecRootCount - XS.Call(LabelName.Get(GCImplementationRefs.DecRootCountRef)); - XS.Label(".AfterGC"); - - XS.Pop(EAX); - XS.Set(name, EAX, destinationIsIndirect: true, destinationDisplacement: 4); - - // Update GC for new object - XS.Compare(name, 0, destinationIsIndirect: true, destinationDisplacement: 4); - XS.Jump(CPU.ConditionalTestEnum.Equal, ".SecondAfterGC"); - XS.Push(name, isIndirect: true, displacement: 4); // push object as pointer/uint to send to IncRootCount - - XS.Call(LabelName.Get(GCImplementationRefs.IncRootCountRef)); - XS.Label(".SecondAfterGC"); - - return; - } - - // value types - - if(!xField.FieldType.IsPointer && !xField.FieldType.IsPrimitive && !xField.FieldType.IsEnum) - { - // let clean up object deal with it - XS.Push(xDataName, isIndirect: true, displacement: 4); - XS.Push(GetTypeIDLabel(xField.FieldType), isIndirect: true); - XS.Call(LabelName.Get(GCImplementationRefs.DecRootCountsInStructRef)); - } - - for (int i = 0; i < xSize / 4; i++) - { - XS.Pop(EAX); - new CPU.Mov { DestinationRef = ElementReference.New(xDataName, i * 4), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.EAX }; - } - switch (xSize % 4) - { - case 1: - { - XS.Pop(EAX); - new CPU.Mov { DestinationRef = ElementReference.New(xDataName, (int)(xSize / 4 * 4)), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.AL }; - break; - } - case 2: - { - XS.Pop(EAX); - new CPU.Mov { DestinationRef = ElementReference.New(xDataName, (int)(xSize / 4 * 4)), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.AX }; - break; - } - case 0: - { - break; - } - default: - throw new NotImplementedException(); - } - - if (!xField.FieldType.IsPointer && !xField.FieldType.IsPrimitive && !xField.FieldType.IsEnum) - { - // let clean up object deal with it - XS.Push(xDataName, isIndirect: true, displacement: 4); - XS.Push(GetTypeIDLabel(xField.FieldType), isIndirect: true); - XS.Call(LabelName.Get(GCImplementationRefs.IncRootCountsInStructRef)); - } - } - - } -} +using System; +using System.Linq; +using System.Reflection; + +using IL2CPU.API; + +using XSharp; +using XSharp.Assembler; +using CPU = XSharp.Assembler.x86; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Stsfld)] + public class Stsfld : ILOp + { + public Stsfld(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = aMethod.MethodBase.DeclaringType; + var xOpCode = (ILOpCodes.OpField)aOpCode; + FieldInfo xField = xOpCode.Value; + var xIsReferenceType = IsReferenceType(xField.FieldType); + + // call cctor: + var xCctor = xField.DeclaringType.GetConstructors(BindingFlags.Static | BindingFlags.NonPublic).SingleOrDefault(); + if (xCctor != null) + { + XS.Call(LabelName.Get(xCctor)); + EmitExceptionLogic(Assembler, aMethod, aOpCode, true, null, ".AfterCCTorExceptionCheck"); + XS.Label(".AfterCCTorExceptionCheck"); + } + + uint xSize = SizeOfType(xField.FieldType); + + XS.Comment("Type = '" + xField.FieldType.FullName + "'"); + uint xOffset = 0; + + var xFields = xField.DeclaringType.GetFields(); + + foreach (FieldInfo xInfo in xFields) + { + if (xInfo == xField) + { + break; + } + + xOffset += SizeOfType(xInfo.FieldType); + } + string xDataName = LabelName.GetStaticFieldName(xField); + + if (xIsReferenceType) + { + var name = ElementReference.New(xDataName).Name; + XS.Add(RSP, 4); + + // GC clean up old object + XS.Compare(name, 0, destinationIsIndirect: true, destinationDisplacement: 4); + XS.Jump(CPU.ConditionalTestEnum.Equal, ".AfterGC"); + XS.Push(name, isIndirect: true, displacement: 4); // push object as pointer to send to DecRootCount + XS.Call(LabelName.Get(GCImplementationRefs.DecRootCountRef)); + XS.Label(".AfterGC"); + + XS.Pop(RAX); + XS.Set(name, RAX, destinationIsIndirect: true, destinationDisplacement: 4); + + // Update GC for new object + XS.Compare(name, 0, destinationIsIndirect: true, destinationDisplacement: 4); + XS.Jump(CPU.ConditionalTestEnum.Equal, ".SecondAfterGC"); + XS.Push(name, isIndirect: true, displacement: 4); // push object as pointer/uint to send to IncRootCount + + XS.Call(LabelName.Get(GCImplementationRefs.IncRootCountRef)); + XS.Label(".SecondAfterGC"); + + return; + } + + // value types + + if(!xField.FieldType.IsPointer && !xField.FieldType.IsPrimitive && !xField.FieldType.IsEnum) + { + // let clean up object deal with it + XS.Push(xDataName, isIndirect: true, displacement: 4); + XS.Push(GetTypeIDLabel(xField.FieldType), isIndirect: true); + XS.Call(LabelName.Get(GCImplementationRefs.DecRootCountsInStructRef)); + } + + for (int i = 0; i < xSize / 4; i++) + { + XS.Pop(RAX); + new CPU.Mov { DestinationRef = ElementReference.New(xDataName, i * 4), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.EAX }; + } + switch (xSize % 4) + { + case 1: + { + XS.Pop(RAX); + new CPU.Mov { DestinationRef = ElementReference.New(xDataName, (int)(xSize / 4 * 4)), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.AL }; + break; + } + case 2: + { + XS.Pop(RAX); + new CPU.Mov { DestinationRef = ElementReference.New(xDataName, (int)(xSize / 4 * 4)), DestinationIsIndirect = true, SourceReg = CPU.RegistersEnum.AX }; + break; + } + case 0: + { + break; + } + default: + throw new NotImplementedException(); + } + + if (!xField.FieldType.IsPointer && !xField.FieldType.IsPrimitive && !xField.FieldType.IsEnum) + { + // let clean up object deal with it + XS.Push(xDataName, isIndirect: true, displacement: 4); + XS.Push(GetTypeIDLabel(xField.FieldType), isIndirect: true); + XS.Call(LabelName.Get(GCImplementationRefs.IncRootCountsInStructRef)); + } + } + + } +} diff --git a/source/Cosmos.IL2CPU/IL/Sub.cs b/source/Cosmos.IL2CPU/IL/Sub.cs index cb59c9a0d..b833d2316 100644 --- a/source/Cosmos.IL2CPU/IL/Sub.cs +++ b/source/Cosmos.IL2CPU/IL/Sub.cs @@ -37,36 +37,36 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) case 4: if (xStackTopIsFloat) { - XS.SSE.MoveSS(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 4); - XS.SSE.MoveSS(XMM1, ESP, sourceIsIndirect: true); + XS.SSE.MoveSS(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 4); + XS.SSE.MoveSS(XMM1, RSP, sourceIsIndirect: true); //XS.LiteralCode("movss XMM1, [ESP + 4]"); XS.SSE.SubSS(XMM1, XMM0); - XS.SSE.MoveSS(ESP, XMM1, destinationIsIndirect: true); + XS.SSE.MoveSS(RSP, XMM1, destinationIsIndirect: true); } else { - XS.Pop(XSRegisters.ECX); - XS.Pop(XSRegisters.EAX); - XS.Sub(XSRegisters.EAX, XSRegisters.ECX); - XS.Push(XSRegisters.EAX); + XS.Pop(XSRegisters.RCX); + XS.Pop(XSRegisters.RAX); + XS.Sub(XSRegisters.RAX, XSRegisters.RCX); + XS.Push(XSRegisters.RAX); } break; case 8: if (xStackTopIsFloat) { - XS.SSE2.MoveSD(XMM0, ESP, sourceIsIndirect: true); - XS.Add(ESP, 8); - XS.SSE2.MoveSD(XMM1, ESP, sourceIsIndirect: true); + XS.SSE2.MoveSD(XMM0, RSP, sourceIsIndirect: true); + XS.Add(RSP, 8); + XS.SSE2.MoveSD(XMM1, RSP, sourceIsIndirect: true); XS.SSE2.SubSD(XMM1, XMM0); - XS.SSE2.MoveSD(ESP, XMM1, destinationIsIndirect: true); + XS.SSE2.MoveSD(RSP, XMM1, destinationIsIndirect: true); } else { - XS.Pop(EAX); - XS.Pop(EDX); - XS.Sub(ESP, EAX, destinationIsIndirect: true); - XS.SubWithCarry(ESP, EDX, destinationDisplacement: 4); + XS.Pop(RAX); + XS.Pop(RDX); + XS.Sub(RSP, RAX, destinationIsIndirect: true); + XS.SubWithCarry(RSP, RDX, destinationDisplacement: 4); } break; default: diff --git a/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs b/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs index cf3030415..a0c5f107f 100644 --- a/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs +++ b/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs @@ -1,66 +1,66 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; -using XSharp.Assembler.x86; -using XSharp; -using static XSharp.XSRegisters; -using System.Reflection; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Sub_Ovf)] - public class Sub_Ovf : ILOp - { - public Sub_Ovf(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - var xIsFloat = TypeIsFloat(xType); - if (xIsFloat) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Sub_Ovf.cs->Error: Expected signed integer operands but get float!"); - } - - if (xSize > 8) - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Sub_Ovf.cs->Error: StackSize > 8 not supported"); - } - else - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - if (xSize > 4) // long - { - XS.Pop(EAX);//low part - XS.Pop(EDX);//high part - XS.Sub(ESP, EAX, destinationIsIndirect: true); - XS.SubWithCarry(ESP, EDX, destinationDisplacement: 4); - - } - else //integer - { - XS.Pop(ECX);//first integer - XS.Pop(EAX);//second integer - XS.Sub(EAX, ECX); - XS.Push(EAX);//push result on stack - } - - // Let's check if we add overflow and if so throw OverflowException - XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel); - if (xSize > 4) // Hack to stop stack corruption - { - XS.Add(ESP, 8); - } - else - { - XS.Add(ESP, 4); - } - Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); - XS.Label(xSuccessLabel); - } - } - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; +using XSharp.Assembler.x86; +using XSharp; +using static XSharp.XSRegisters; +using System.Reflection; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Sub_Ovf)] + public class Sub_Ovf : ILOp + { + public Sub_Ovf(XSharp.Assembler.Assembler aAsmblr) : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + var xIsFloat = TypeIsFloat(xType); + if (xIsFloat) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Sub_Ovf.cs->Error: Expected signed integer operands but get float!"); + } + + if (xSize > 8) + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Sub_Ovf.cs->Error: StackSize > 8 not supported"); + } + else + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + if (xSize > 4) // long + { + XS.Pop(RAX);//low part + XS.Pop(RDX);//high part + XS.Sub(RSP, RAX, destinationIsIndirect: true); + XS.SubWithCarry(RSP, RDX, destinationDisplacement: 4); + + } + else //integer + { + XS.Pop(RCX);//first integer + XS.Pop(RAX);//second integer + XS.Sub(RAX, RCX); + XS.Push(RAX);//push result on stack + } + + // Let's check if we add overflow and if so throw OverflowException + XS.Jump(ConditionalTestEnum.NoOverflow, xSuccessLabel); + if (xSize > 4) // Hack to stop stack corruption + { + XS.Add(RSP, 8); + } + else + { + XS.Add(RSP, 4); + } + Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); + XS.Label(xSuccessLabel); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs b/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs index b91207a43..5154e012f 100644 --- a/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs @@ -1,64 +1,64 @@ -using System; -using CPUx86 = XSharp.Assembler.x86; -using XSharp.Assembler.x86; -using XSharp; -using static XSharp.XSRegisters; -using System.Reflection; - -namespace Cosmos.IL2CPU.X86.IL -{ - [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Sub_Ovf_Un)] - public class Sub_Ovf_Un: ILOp - { - public Sub_Ovf_Un(XSharp.Assembler.Assembler aAsmblr):base(aAsmblr) { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { - // TODO overflow check for float - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - var xIsFloat = TypeIsFloat(xType); - - if (xIsFloat) - { - throw new Exception("Cosmos.IL2CPU.x86->IL->Sub_Ovf_Un.cs->Error: Expected unsigned integer operands but get float!"); - } - - if (xSize > 8) - { - //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Sub_Ovf_Un.cs->Error: StackSize > 8 not supported"); - } - else - { - var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; - var xSuccessLabel = xBaseLabel + "Success"; - if (xSize > 4) // long - { - XS.Pop(EDX); // low part - XS.Pop(EAX); // high part - XS.Sub(ESP, EDX, destinationIsIndirect: true); - XS.SubWithCarry(ESP, EAX, destinationDisplacement: 4); - } - else //integer - { - XS.Pop(EAX); - XS.Sub(ESP, EAX, destinationIsIndirect: true); - } - - // Let's check if we add overflow and if so throw OverflowException - XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); - if (xSize > 4) // Hack to stop stack corruption - { - XS.Add(ESP, 8); - } - else - { - XS.Add(ESP, 4); - } - Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); - XS.Label(xSuccessLabel); - } - } - } -} +using System; +using CPUx86 = XSharp.Assembler.x86; +using XSharp.Assembler.x86; +using XSharp; +using static XSharp.XSRegisters; +using System.Reflection; + +namespace Cosmos.IL2CPU.X86.IL +{ + [Cosmos.IL2CPU.OpCode(ILOpCode.Code.Sub_Ovf_Un)] + public class Sub_Ovf_Un: ILOp + { + public Sub_Ovf_Un(XSharp.Assembler.Assembler aAsmblr):base(aAsmblr) { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { + // TODO overflow check for float + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + var xIsFloat = TypeIsFloat(xType); + + if (xIsFloat) + { + throw new Exception("Cosmos.IL2CPU.x86->IL->Sub_Ovf_Un.cs->Error: Expected unsigned integer operands but get float!"); + } + + if (xSize > 8) + { + //EmitNotImplementedException( Assembler, aServiceProvider, "Size '" + xSize.Size + "' not supported (add)", aCurrentLabel, aCurrentMethodInfo, aCurrentOffset, aNextLabel ); + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Sub_Ovf_Un.cs->Error: StackSize > 8 not supported"); + } + else + { + var xBaseLabel = GetLabel(aMethod, aOpCode) + "."; + var xSuccessLabel = xBaseLabel + "Success"; + if (xSize > 4) // long + { + XS.Pop(RDX); // low part + XS.Pop(RAX); // high part + XS.Sub(RSP, RDX, destinationIsIndirect: true); + XS.SubWithCarry(RSP, RAX, destinationDisplacement: 4); + } + else //integer + { + XS.Pop(RAX); + XS.Sub(RSP, RAX, destinationIsIndirect: true); + } + + // Let's check if we add overflow and if so throw OverflowException + XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); + if (xSize > 4) // Hack to stop stack corruption + { + XS.Add(RSP, 8); + } + else + { + XS.Add(RSP, 4); + } + Call.DoExecute(Assembler, aMethod, typeof(ExceptionHelper).GetMethod("ThrowOverflow", BindingFlags.Static | BindingFlags.Public), aOpCode, GetLabel(aMethod, aOpCode), xSuccessLabel, DebugEnabled); + XS.Label(xSuccessLabel); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Switch.cs b/source/Cosmos.IL2CPU/IL/Switch.cs index 0785777ce..5b3b38d6c 100644 --- a/source/Cosmos.IL2CPU/IL/Switch.cs +++ b/source/Cosmos.IL2CPU/IL/Switch.cs @@ -1,28 +1,28 @@ -using XSharp; -using XSharp.Assembler.x86; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Switch)] - public class Switch : ILOp - { - public Switch(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - ILOpCodes.OpSwitch OpSw = (ILOpCodes.OpSwitch)aOpCode; - XS.Pop(XSRegisters.EAX); - - for (int i = 0; i < OpSw.BranchLocations.Length; i++) - { - string xDestLabel = AppAssembler.TmpPosLabel(aMethod, OpSw.BranchLocations[i]); - - XS.Compare(XSRegisters.EAX, (uint)i); - XS.Jump(ConditionalTestEnum.Equal, xDestLabel); - } - } - } -} +using XSharp; +using XSharp.Assembler.x86; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Switch)] + public class Switch : ILOp + { + public Switch(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + ILOpCodes.OpSwitch OpSw = (ILOpCodes.OpSwitch)aOpCode; + XS.Pop(XSRegisters.RAX); + + for (int i = 0; i < OpSw.BranchLocations.Length; i++) + { + string xDestLabel = AppAssembler.TmpPosLabel(aMethod, OpSw.BranchLocations[i]); + + XS.Compare(XSRegisters.RAX, (uint)i); + XS.Jump(ConditionalTestEnum.Equal, xDestLabel); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Throw.cs b/source/Cosmos.IL2CPU/IL/Throw.cs index a51777033..40b29c755 100644 --- a/source/Cosmos.IL2CPU/IL/Throw.cs +++ b/source/Cosmos.IL2CPU/IL/Throw.cs @@ -1,37 +1,37 @@ -using IL2CPU.API; - -using XSharp; -using XSharp.Assembler; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Throw)] - public class Throw : ILOp - { - public Throw(Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - // TODO: Implement exception - DoNullReferenceCheck(Assembler, DebugEnabled, 4); - XS.Add(ESP, 4); - XS.Pop(EAX); - XS.Set(LabelName.GetStaticFieldName(ExceptionHelperRefs.CurrentExceptionRef), EAX, destinationIsIndirect: true); - XS.Call("SystemExceptionOccurred"); - XS.Set(ECX, 3); - EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null); - - // FIXME: This is only temporary, but this is better to avoid potential CPU faults if the code still gets executed (aka the exception was not handled before) - var xBaseLabel = GetLabel(aMethod, aOpCode); - var xLoop = xBaseLabel + "_Loop"; - - XS.Label(xLoop); - XS.Halt(); - XS.Jump(xLoop); - } - } -} +using IL2CPU.API; + +using XSharp; +using XSharp.Assembler; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Throw)] + public class Throw : ILOp + { + public Throw(Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + // TODO: Implement exception + DoNullReferenceCheck(Assembler, DebugEnabled, 4); + XS.Add(RSP, 4); + XS.Pop(RAX); + XS.Set(LabelName.GetStaticFieldName(ExceptionHelperRefs.CurrentExceptionRef), RAX, destinationIsIndirect: true); + XS.Call("SystemExceptionOccurred"); + XS.Set(RCX, 3); + EmitExceptionLogic(Assembler, aMethod, aOpCode, false, null); + + // FIXME: This is only temporary, but this is better to avoid potential CPU faults if the code still gets executed (aka the exception was not handled before) + var xBaseLabel = GetLabel(aMethod, aOpCode); + var xLoop = xBaseLabel + "_Loop"; + + XS.Label(xLoop); + XS.Halt(); + XS.Jump(xLoop); + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Unbox.cs b/source/Cosmos.IL2CPU/IL/Unbox.cs index 6890da9f8..2f7d044ee 100644 --- a/source/Cosmos.IL2CPU/IL/Unbox.cs +++ b/source/Cosmos.IL2CPU/IL/Unbox.cs @@ -24,7 +24,7 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) var xAfterIsInstanceCallLabel = xOpLabel + ".AfterIsInstanceCall"; var xAfterInstanceCheckLabel = xOpLabel + ".AfterInstanceCheck"; - XS.Add(ESP, 4); + XS.Add(RSP, 4); var xIsNullable = xType.IsGenericType && xType.GetGenericTypeDefinition() == typeof(Nullable<>); @@ -32,7 +32,7 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) { xType = xType.GenericTypeArguments[0]; - XS.Compare(ESP, 0, destinationIsIndirect: true); + XS.Compare(RSP, 0, destinationIsIndirect: true); XS.Jump(ConditionalTestEnum.Equal, xAfterInstanceCheckLabel); } else @@ -42,17 +42,17 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) var xTypeId = GetTypeIDLabel(xType); - XS.Set(EAX, ESP, sourceIsIndirect: true); - XS.Push(EAX, isIndirect: true); + XS.Set(RAX, RSP, sourceIsIndirect: true); + XS.Push(RAX, isIndirect: true); XS.Push(xTypeId, isIndirect: true); XS.Push(Convert.ToUInt32(xType.IsInterface)); Call.DoExecute(Assembler, aMethod, VTablesImplRefs.IsInstanceRef, aOpCode, GetLabel(aMethod, aOpCode), xAfterIsInstanceCallLabel, DebugEnabled); XS.Label(xAfterIsInstanceCallLabel); - XS.Pop(EAX); + XS.Pop(RAX); - XS.Compare(EAX, 0); + XS.Compare(RAX, 0); XS.Jump(ConditionalTestEnum.NotEqual, xAfterInstanceCheckLabel); XS.Call(LabelName.Get(ExceptionHelperRefs.ThrowInvalidCastExceptionRef)); @@ -80,7 +80,7 @@ public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) } // the result is a managed pointer, it should be tracked by GC - XS.Add(ESP, ObjectUtils.FieldDataOffset, destinationIsIndirect: true); + XS.Add(RSP, ObjectUtils.FieldDataOffset, destinationIsIndirect: true); } } } diff --git a/source/Cosmos.IL2CPU/IL/Xor.cs b/source/Cosmos.IL2CPU/IL/Xor.cs index 8c5422f53..935c1f2ac 100644 --- a/source/Cosmos.IL2CPU/IL/Xor.cs +++ b/source/Cosmos.IL2CPU/IL/Xor.cs @@ -1,39 +1,39 @@ -using System; - -using XSharp; -using static XSharp.XSRegisters; - -namespace Cosmos.IL2CPU.X86.IL -{ - [OpCode(ILOpCode.Code.Xor)] - public class Xor : ILOp - { - public Xor(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } - - public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - - if (xSize <= 4) - { - XS.Pop(EAX); - XS.Xor(ESP, EAX, destinationIsIndirect: true); - } - else if (xSize <= 8) - { - XS.Pop(EAX); - XS.Pop(EDX); - XS.Xor(ESP, EAX, destinationIsIndirect: true); - XS.Xor(ESP, EDX, destinationDisplacement: 4); - } - else - { - throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Xor.cs->Error: StackSize > 8 not supported"); - } - } - } -} +using System; + +using XSharp; +using static XSharp.XSRegisters; + +namespace Cosmos.IL2CPU.X86.IL +{ + [OpCode(ILOpCode.Code.Xor)] + public class Xor : ILOp + { + public Xor(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) + { + } + + public override void Execute(Il2cpuMethodInfo aMethod, ILOpCode aOpCode) + { + var xType = aOpCode.StackPopTypes[0]; + var xSize = SizeOfType(xType); + + if (xSize <= 4) + { + XS.Pop(RAX); + XS.Xor(RSP, RAX, destinationIsIndirect: true); + } + else if (xSize <= 8) + { + XS.Pop(RAX); + XS.Pop(RDX); + XS.Xor(RSP, RAX, destinationIsIndirect: true); + XS.Xor(RSP, RDX, destinationDisplacement: 4); + } + else + { + throw new NotImplementedException("Cosmos.IL2CPU.x86->IL->Xor.cs->Error: StackSize > 8 not supported"); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/ILOp.cs b/source/Cosmos.IL2CPU/ILOp.cs index 6e201f1b9..83811ee18 100644 --- a/source/Cosmos.IL2CPU/ILOp.cs +++ b/source/Cosmos.IL2CPU/ILOp.cs @@ -122,7 +122,7 @@ public static uint GetEBPOffsetForLocal(Il2cpuMethodInfo aMethod, int localIndex break; } var xField = xLocalInfos[i]; - xOffset += GetStackCountForLocal(aMethod, xField.LocalType) * 4; + xOffset += GetStackCountForLocal(aMethod, xField.LocalType) * 8; } return xOffset; } @@ -133,7 +133,7 @@ public static uint GetEBPOffsetForLocalForDebugger(Il2cpuMethodInfo aMethod, int uint xOffset = GetEBPOffsetForLocal(aMethod, localIndex); var xLocalInfos = aMethod.MethodBase.GetLocalVariables(); var xField = xLocalInfos[localIndex]; - xOffset += GetStackCountForLocal(aMethod, xField.LocalType) * 4 - 4; + xOffset += GetStackCountForLocal(aMethod, xField.LocalType) * 8 - 4; return xOffset; } @@ -395,7 +395,7 @@ public static void EmitExceptionCleanupAfterCall(Assembler aAssembler, uint aRet XS.Comment("Cleanup return"); // cleanup result values - XS.Add(XSRegisters.ESP, 4 * aReturnSize / 4); + XS.Add(XSRegisters.RSP, 4 * aReturnSize / 4); } if (aStackSizeBeforeCall > aTotalArgumentSizeOfMethod) @@ -406,7 +406,7 @@ public static void EmitExceptionCleanupAfterCall(Assembler aAssembler, uint aRet XS.Comment("Cleanup extra stack"); // cleanup result values - XS.Add(XSRegisters.ESP, 4 * xExtraStack / 4); + XS.Add(XSRegisters.RSP, 4 * xExtraStack / 4); } } } @@ -462,7 +462,7 @@ public static void EmitExceptionLogic(Assembler aAssembler, Il2cpuMethodInfo aMe } else { - XS.Test(ECX, 2); + XS.Test(RCX, 2); if (aCleanup != null) { @@ -501,15 +501,15 @@ protected static void DoNullReferenceCheck(Assembler assembler, bool debugEnable if (debugEnabled) { //if (!CompilerEngine.UseGen3Kernel) { - XS.Compare(ESP, 0, destinationDisplacement: stackOffsetToCheck); + XS.Compare(RSP, 0, destinationDisplacement: stackOffsetToCheck); XS.Jump(CPU.ConditionalTestEnum.NotEqual, ".AfterNullCheck"); XS.ClearInterruptFlag(); XS.Exchange(BX, BX); // don't remove the call. It seems pointless, but we need it to retrieve the EIP value XS.Call(".NullCheck_GetCurrAddress"); XS.Label(".NullCheck_GetCurrAddress"); - XS.Pop(EAX); - XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], EAX, destinationIsIndirect: true); + XS.Pop(RAX); + XS.Set(AsmMarker.Labels[AsmMarker.Type.DebugStub_CallerEIP], RAX, destinationIsIndirect: true); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_SendNullRefEvent]); //} XS.Halt(); diff --git a/source/Cosmos.IL2CPU/Program.cs b/source/Cosmos.IL2CPU/Program.cs index 7c8f8e0de..bc410a7a9 100644 --- a/source/Cosmos.IL2CPU/Program.cs +++ b/source/Cosmos.IL2CPU/Program.cs @@ -19,7 +19,7 @@ public static int Run(string[] aArgs, Action aLogMessage, Action while (!Debugger.IsAttached) { - Debugger.Break(); + //Debugger.Break(); } } From ec802a97c99047fad1bba34f5ad4ae312db31f56 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:59:11 -0500 Subject: [PATCH 3/4] debugging --- source/Cosmos.IL2CPU/CosmosAssembler.cs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/source/Cosmos.IL2CPU/CosmosAssembler.cs b/source/Cosmos.IL2CPU/CosmosAssembler.cs index b70a80e2e..d87823407 100644 --- a/source/Cosmos.IL2CPU/CosmosAssembler.cs +++ b/source/Cosmos.IL2CPU/CosmosAssembler.cs @@ -335,7 +335,7 @@ public void Initialize(bool enableVBE, string VBEResolution) // This is our first entry point. Multiboot uses this as Cosmos entry point. new Label("Kernel_Start", isGlobal: true); - XS.Set(RSP, "Kernel_Stack"); + //XS.Set(RSP, "Kernel_Stack"); // limine protocol already sets up stack (64KB) // Displays "Cosmos" in top left. Used to make sure Cosmos is booted in case of hang. // ie bootloader debugging. This must be the FIRST code, even before setup so we know @@ -344,7 +344,7 @@ public void Initialize(bool enableVBE, string VBEResolution) WriteDebugVideo("Cosmos pre boot"); // For when using Bochs, causes a break ASAP on entry after initial Cosmos display. - //new LiteralAssemblerCode("xchg bx, bx"); + new LiteralAssemblerCode("xchg bx, bx"); // CLI ASAP WriteDebugVideo("Clearing interrupts."); @@ -365,16 +365,16 @@ public void Initialize(bool enableVBE, string VBEResolution) SourceReg = RegistersEnum.EBX }; - XS.Call(LabelName.Get(CompilerEngine.TypeResolver.ResolveType("Cosmos.Core.Multiboot.Multiboot2, Cosmos.Core", true).GetMethod("Init"))); + //XS.Call(LabelName.Get(CompilerEngine.TypeResolver.ResolveType("Cosmos.Core.Multiboot.Multiboot2, Cosmos.Core", true).GetMethod("Init"))); new Comment(this, "END - Multiboot Info"); new LiteralAssemblerCode("%endif"); - WriteDebugVideo("Creating GDT."); - //CreateGDT(); //limine creates the GDT for us - + WriteDebugVideo("Creating GDT."); + //CreateGDT(); //limine creates the GDT for us + new LiteralAssemblerCode("xchg bx, bx"); WriteDebugVideo("Configuring PIC"); - ConfigurePIC(); - + ConfigurePIC(); + new LiteralAssemblerCode("xchg bx, bx"); WriteDebugVideo("Creating IDT."); CreateIDT(); @@ -401,8 +401,8 @@ public void Initialize(bool enableVBE, string VBEResolution) { WriteDebugVideo("Initializing DebugStub."); XS.Call(AsmMarker.Labels[AsmMarker.Type.DebugStub_Init]); - } - + } + new LiteralAssemblerCode("xchg bx, bx"); //Initiate Memory WriteDebugVideo("Initiating Memory"); XS.Call(LabelName.Get(GCImplementationRefs.InitRef)); @@ -599,7 +599,7 @@ protected override void BeforeFlushText(TextWriter aOutput) protected override void OnBeforeFlush(TextWriter output) { - DataMembers.AddRange(new DataMember[] { new DataMember("_end_data", Array.Empty()) }); + // DataMembers.AddRange(new DataMember[] { new DataMember("_end_data", Array.Empty()) }); //output.WriteLine("section .text"); } From 0aae4cc0add3178fc2a2bcd3cd6ea3bb2de80f82 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:04:39 -0500 Subject: [PATCH 4/4] Update CosmosAssembler.cs --- source/Cosmos.IL2CPU/CosmosAssembler.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/Cosmos.IL2CPU/CosmosAssembler.cs b/source/Cosmos.IL2CPU/CosmosAssembler.cs index d87823407..288dbd642 100644 --- a/source/Cosmos.IL2CPU/CosmosAssembler.cs +++ b/source/Cosmos.IL2CPU/CosmosAssembler.cs @@ -597,10 +597,8 @@ protected override void BeforeFlushText(TextWriter aOutput) aOutput.WriteLine("section .data"); } - protected override void OnBeforeFlush(TextWriter output) + protected override void OnBeforeFlush() { - // DataMembers.AddRange(new DataMember[] { new DataMember("_end_data", Array.Empty()) }); - //output.WriteLine("section .text"); } protected override void OnFlushTextAfterEmitEverything(TextWriter aOutput)