diff --git a/source/Cosmos.IL2CPU/IL/Add_Ovf.cs b/source/Cosmos.IL2CPU/IL/Add_Ovf.cs index 708177bc7..bbb882610 100644 --- a/source/Cosmos.IL2CPU/IL/Add_Ovf.cs +++ b/source/Cosmos.IL2CPU/IL/Add_Ovf.cs @@ -2,58 +2,67 @@ 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 + [OpCode(ILOpCode.Code.Add_Ovf)] + public class Add_Ovf : ILOp + { + public Add_Ovf(XSharp.Assembler.Assembler aAsmblr) + : base(aAsmblr) { - public Add_Ovf(XSharp.Assembler.Assembler aAsmblr) - : base(aAsmblr) - { - } + } - public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) - { - var xType = aOpCode.StackPopTypes[0]; - var xSize = SizeOfType(xType); - var xIsFloat = TypeIsFloat(xType); + public override void Execute(_MethodInfo 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 (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); + 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 - { + } + else //integer + { - XS.Pop(EAX); - XS.Add(ESP, EAX, destinationIsIndirect: true); - } + 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); - ThrowOverflowException(); - XS.Label(xSuccessLabel); - } + // 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); + } } + } } diff --git a/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs b/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs index 5859e53c1..2d0ae5103 100644 --- a/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Add_Ovf_Un.cs @@ -2,6 +2,7 @@ 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 @@ -50,9 +51,17 @@ public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) // Let's check if we add overflow and if so throw OverflowException XS.Jump(ConditionalTestEnum.NotCarry, xSuccessLabel); - ThrowOverflowException(); + 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); - } + } } } } diff --git a/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs b/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs index ca8c056a2..8b4c87303 100644 --- a/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs +++ b/source/Cosmos.IL2CPU/IL/Sub_Ovf.cs @@ -1,21 +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) { - } + [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(_MethodInfo 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 + } - public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { - //if (Assembler.Stack.Peek().IsFloat) { - // throw new NotImplementedException("Sub_Ovf: TODO need to call Sub IL"); - //} - throw new NotImplementedException(); - } - } -} \ No newline at end of file + // 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); + } + } + } +} diff --git a/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs b/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs index f8ef38fe1..fda3410b5 100644 --- a/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs +++ b/source/Cosmos.IL2CPU/IL/Sub_Ovf_Un.cs @@ -1,7 +1,9 @@ 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 { @@ -12,10 +14,51 @@ public Sub_Ovf_Un(XSharp.Assembler.Assembler aAsmblr):base(aAsmblr) { } public override void Execute(_MethodInfo aMethod, ILOpCode aOpCode) { - //if (Assembler.Stack.Peek().IsFloat) { - // throw new NotImplementedException("Sub_Ovf_Un: TODO need to call Sub IL"); - //} - throw new NotImplementedException(); + // 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.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); + } } } -} \ No newline at end of file +} diff --git a/source/Cosmos.IL2CPU/ILOpCodes/OpNone.cs b/source/Cosmos.IL2CPU/ILOpCodes/OpNone.cs index 057d354c7..681ffd818 100644 --- a/source/Cosmos.IL2CPU/ILOpCodes/OpNone.cs +++ b/source/Cosmos.IL2CPU/ILOpCodes/OpNone.cs @@ -67,12 +67,15 @@ public override int GetNumberOfStackPops(MethodBase aMethod) return 1; case Code.Add: case Code.Add_Ovf: + case Code.Add_Ovf_Un: case Code.Mul: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Div: case Code.Div_Un: case Code.Sub: + case Code.Sub_Ovf: + case Code.Sub_Ovf_Un: case Code.Rem: case Code.Rem_Un: case Code.Xor: @@ -208,12 +211,15 @@ public override int GetNumberOfStackPushes(MethodBase aMethod) return 1; case Code.Add: case Code.Add_Ovf: + case Code.Add_Ovf_Un: case Code.Mul: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Div: case Code.Div_Un: case Code.Sub: + case Code.Sub_Ovf: + case Code.Sub_Ovf_Un: case Code.Rem: case Code.Rem_Un: case Code.Xor: @@ -529,12 +535,16 @@ protected override void DoInterpretStackTypes(ref bool aSituationChanged) switch (OpCode) { case Code.Add: + case Code.Add_Ovf: + case Code.Add_Ovf_Un: case Code.Mul: case Code.Mul_Ovf: case Code.Mul_Ovf_Un: case Code.Div: case Code.Div_Un: case Code.Sub: + case Code.Sub_Ovf: + case Code.Sub_Ovf_Un: case Code.Rem: case Code.Rem_Un: case Code.Xor: