From 51e893eb744b2b8f102f9e6a03e577b443fe75c8 Mon Sep 17 00:00:00 2001 From: Trivalik_cp <42497cfff885d3ca0e6fda54fb6262dd42101bd5sx56jUzf> Date: Fri, 2 Sep 2011 21:03:14 +0000 Subject: [PATCH] add movsx, fchs implement neg CIL (needed for Abs()) fix floor and ceiling in range of int add sign extension to LdArg and LdLoc remove unneeded math functions, like min,max,abs --- .../Cosmos.Compiler.Assembler.X86.csproj | 2 + .../MoveSignExtend.cs | 24 +++ .../x87/FloatNegate.cs | 7 + source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldarg.cs | 31 +-- source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldloc.cs | 14 +- source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Mul.cs | 9 +- source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Neg.cs | 61 ++++-- .../Cosmos.System.Plugs.System/MathImpl.cs | 187 +++--------------- 8 files changed, 127 insertions(+), 208 deletions(-) create mode 100644 source2/Compiler/Cosmos.Compiler.Assembler.X86/MoveSignExtend.cs create mode 100644 source2/Compiler/Cosmos.Compiler.Assembler.X86/x87/FloatNegate.cs diff --git a/source2/Compiler/Cosmos.Compiler.Assembler.X86/Cosmos.Compiler.Assembler.X86.csproj b/source2/Compiler/Cosmos.Compiler.Assembler.X86/Cosmos.Compiler.Assembler.X86.csproj index fcc0dcae8..5fd3eca20 100644 --- a/source2/Compiler/Cosmos.Compiler.Assembler.X86/Cosmos.Compiler.Assembler.X86.csproj +++ b/source2/Compiler/Cosmos.Compiler.Assembler.X86/Cosmos.Compiler.Assembler.X86.csproj @@ -64,6 +64,7 @@ + @@ -75,6 +76,7 @@ + diff --git a/source2/Compiler/Cosmos.Compiler.Assembler.X86/MoveSignExtend.cs b/source2/Compiler/Cosmos.Compiler.Assembler.X86/MoveSignExtend.cs new file mode 100644 index 000000000..3120ad81a --- /dev/null +++ b/source2/Compiler/Cosmos.Compiler.Assembler.X86/MoveSignExtend.cs @@ -0,0 +1,24 @@ +namespace Cosmos.Compiler.Assembler.X86 { + [OpCode("movsx")] + public class MoveSignExtend : InstructionWithDestinationAndSourceAndSize + { + + public override void WriteText(Assembler aAssembler, System.IO.TextWriter aOutput) + { + if (Size == 0) + { + Size = 32; + } + aOutput.Write(mMnemonic); + if (!DestinationEmpty) + { + aOutput.Write(" "); + aOutput.Write(this.GetDestinationAsString()); + aOutput.Write(", "); + aOutput.Write(SizeToString(Size)); + aOutput.Write(" "); + aOutput.Write(this.GetSourceAsString()); + } + } + } +} \ No newline at end of file diff --git a/source2/Compiler/Cosmos.Compiler.Assembler.X86/x87/FloatNegate.cs b/source2/Compiler/Cosmos.Compiler.Assembler.X86/x87/FloatNegate.cs new file mode 100644 index 000000000..8dbe7d771 --- /dev/null +++ b/source2/Compiler/Cosmos.Compiler.Assembler.X86/x87/FloatNegate.cs @@ -0,0 +1,7 @@ +namespace Cosmos.Compiler.Assembler.X86.x87 +{ + [OpCode("fchs")] + public class FloatNegate : Instruction + { + } +} \ No newline at end of file diff --git a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldarg.cs b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldarg.cs index 7b571a719..429ccab24 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldarg.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldarg.cs @@ -3,6 +3,7 @@ using Cosmos.IL2CPU.ILOpCodes; using Cosmos.IL2CPU.X86; using Cosmos.Compiler.Assembler; using Cosmos.Compiler.Assembler.X86; +using CPUx86 = Cosmos.Compiler.Assembler.X86; namespace Cosmos.IL2CPU.X86.IL { @@ -83,7 +84,6 @@ namespace Cosmos.IL2CPU.X86.IL } public static void DoExecute(Assembler Assembler, MethodInfo aMethod, ushort aParam) { - uint xArgSize = 0u; var xDisplacement = GetArgumentDisplacement(aMethod, aParam); Type xArgType; if (aMethod.MethodBase.IsStatic) { @@ -101,16 +101,25 @@ namespace Cosmos.IL2CPU.X86.IL } new Comment("Ldarg"); new Comment("Arg idx = " + aParam); - xArgSize = Align(SizeOfType(xArgType), 4); - new Comment("Arg type = " + xArgType.ToString()); - new Comment("Arg size = " + xArgSize); - for (int i = 0; i < (xArgSize / 4); i++) { - new Push { - DestinationReg = Registers.EBP, - DestinationIsIndirect = true, - DestinationDisplacement = (int)(xDisplacement - (i * 4)) - }; - } + uint xArgRealSize = SizeOfType(xArgType); + uint xArgSize = Align(xArgRealSize, 4); + new Comment("Arg type = " + xArgType.ToString()); + new Comment("Arg real size = " + xArgRealSize + " aligned size = " + xArgSize); + if (xArgRealSize < 4) + { + new CPUx86.MoveSignExtend { DestinationReg = CPUx86.Registers.EAX, Size = (byte)(xArgRealSize * 8), SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = xDisplacement }; + new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + } + else + { + for (int i = 0; i < (xArgSize / 4); i++) { + new Push { + DestinationReg = Registers.EBP, + DestinationIsIndirect = true, + DestinationDisplacement = xDisplacement - (i * 4) + }; + } + } Assembler.Stack.Push(xArgSize, xArgType); } } diff --git a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldloc.cs b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldloc.cs index 3316f0aae..bcef9d5ec 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldloc.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Ldloc.cs @@ -34,16 +34,9 @@ namespace Cosmos.IL2CPU.X86.IL switch (xSize) { case 1: - { - new CPUx86.Xor { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX }; - new CPUx86.Move { DestinationReg = CPUx86.Registers.AL, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; - break; - } case 2: { - new CPUx86.Xor { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.EAX }; - new CPUx86.Move { DestinationReg = CPUx86.Registers.AX, SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset }; + new CPUx86.MoveSignExtend { DestinationReg = CPUx86.Registers.EAX, Size = (byte)(xSize * 8), SourceReg = CPUx86.Registers.EBP, SourceIsIndirect = true, SourceDisplacement = 0 - xEBPOffset }; new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; break; } @@ -53,13 +46,8 @@ namespace Cosmos.IL2CPU.X86.IL break; } } - } -#if DOTNETCOMPATIBLE Assembler.Stack.Push(ILOp.Align(xSize, 4), xVar.LocalType); -#else - Assembler.Stack.Push(xSize, xVar.LocalType); -#endif } } } \ No newline at end of file diff --git a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Mul.cs b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Mul.cs index 7e0924237..ecbcc8f5f 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Mul.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Mul.cs @@ -1,6 +1,5 @@ using System; using CPUx86 = Cosmos.Compiler.Assembler.X86; -using Cosmos.Compiler.Assembler.X86; using Label = Cosmos.Compiler.Assembler.Label; namespace Cosmos.IL2CPU.X86.IL { @@ -19,10 +18,10 @@ namespace Cosmos.IL2CPU.X86.IL { if (xStackContent.IsFloat) { - new CPUx86.x87.FloatLoad { DestinationReg = Registers.ESP, Size = 64, DestinationIsIndirect = true }; - new CPUx86.Add { SourceValue = 8, DestinationReg = Registers.ESP }; + new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true }; + new CPUx86.Add { SourceValue = 8, DestinationReg = CPUx86.Registers.ESP }; new CPUx86.x87.FloatMul { DestinationReg = CPUx86.Registers.ESP, DestinationIsIndirect = true, Size = 64 }; - new CPUx86.x87.FloatStoreAndPop { DestinationReg = Registers.ESP, Size = 64, DestinationIsIndirect = true }; + new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true }; } else { @@ -47,7 +46,7 @@ namespace Cosmos.IL2CPU.X86.IL //mov RIGHT_HIGH to eax, is useable on Full 64 multiply new CPUx86.Move { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 4 }; new CPUx86.Compare { DestinationReg = CPUx86.Registers.EAX, SourceReg = CPUx86.Registers.ESP, SourceIsIndirect = true, SourceDisplacement = 12 }; - new CPUx86.ConditionalJump { Condition = ConditionalTestEnum.Zero, DestinationLabel = Simple32Multiply }; + new CPUx86.ConditionalJump { Condition = CPUx86.ConditionalTestEnum.Zero, DestinationLabel = Simple32Multiply }; // Full 64 Multiply // eax contains already RIGHT_HIGH diff --git a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Neg.cs b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Neg.cs index ea92c5dd3..d35f482b6 100644 --- a/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Neg.cs +++ b/source2/IL2CPU/Cosmos.IL2CPU.X86/IL/Neg.cs @@ -3,20 +3,51 @@ using CPUx86 = Cosmos.Compiler.Assembler.X86; namespace Cosmos.IL2CPU.X86.IL { - [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )] - public class Neg : ILOp - { - public Neg( Cosmos.Compiler.Assembler.Assembler aAsmblr ) - : base( aAsmblr ) - { - } + [Cosmos.IL2CPU.OpCode( ILOpCode.Code.Neg )] + public class Neg : ILOp + { + public Neg( Cosmos.Compiler.Assembler.Assembler aAsmblr ) + : base( aAsmblr ) + { + } - public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) - { - new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Neg { DestinationReg = CPUx86.Registers.EAX }; - new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; - } - - } + public override void Execute( MethodInfo aMethod, ILOpCode aOpCode ) + { + var xStackContent = Assembler.Stack.Peek(); + if (xStackContent.Size > 4) + { + if (xStackContent.IsFloat) + { + new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true }; + new CPUx86.x87.FloatNegate { }; + new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 64, DestinationIsIndirect = true }; + } + else + { + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EBX }; // low + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; // high + new CPUx86.Neg { DestinationReg = CPUx86.Registers.EBX }; // set carry if EBX != 0 + new CPUx86.AddWithCarry { DestinationReg = CPUx86.Registers.EAX, SourceValue = 0 }; + new CPUx86.Neg { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Push { DestinationReg = CPUx86.Registers.EBX }; + } + } + else + { + if (xStackContent.IsFloat) + { + new CPUx86.x87.FloatLoad { DestinationReg = CPUx86.Registers.ESP, Size = 32, DestinationIsIndirect = true }; + new CPUx86.x87.FloatNegate { }; + new CPUx86.x87.FloatStoreAndPop { DestinationReg = CPUx86.Registers.ESP, Size = 32, DestinationIsIndirect = true }; + } + else + { + new CPUx86.Pop { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Neg { DestinationReg = CPUx86.Registers.EAX }; + new CPUx86.Push { DestinationReg = CPUx86.Registers.EAX }; + } + } + } + } } diff --git a/source2/Kernel/System/Cosmos.System.Plugs.System/MathImpl.cs b/source2/Kernel/System/Cosmos.System.Plugs.System/MathImpl.cs index 8317168a1..907887545 100644 --- a/source2/Kernel/System/Cosmos.System.Plugs.System/MathImpl.cs +++ b/source2/Kernel/System/Cosmos.System.Plugs.System/MathImpl.cs @@ -12,6 +12,7 @@ namespace Cosmos.System.Plugs.System public const double PI = 3.14159265358979; public const double E = 2.71828182845905; + // TODO Abs decimal #region Abs public static double Abs(double value) { @@ -37,6 +38,7 @@ namespace Cosmos.System.Plugs.System } } + /* should work from ms .net public static long Abs(long value) { if (value < 0) @@ -59,23 +61,13 @@ namespace Cosmos.System.Plugs.System { return value; } - } + }*/ #endregion + // TODO Max decimal #region Max - public static byte Max(byte val1, byte val2) - { - if (val1 > val2) - { - return val1; - } - else - { - return val2; - } - } - - //public static decimal Max(decimal val1, decimal val2) + + //public static decimal Max(decimal val1, decimal val2) //{ // if (val1 > val2) // { @@ -87,79 +79,10 @@ namespace Cosmos.System.Plugs.System // } //} - public static double Max(double val1, double val2) - { - if (val1 > val2) - { - return val1; - } - else - { - return val2; - } - } - - public static short Max(short val1, short val2) - { - if (val1 > val2) - { - return val1; - } - else - { - return val2; - } - } - - public static int Max(int val1, int val2) - { - if (val1 > val2) - { - return val1; - } - else - { - return val2; - } - } - - public static long Max(long val1, long val2) - { - if (val1 > val2) - { - return val1; - } - else - { - return val2; - } - } - - public static float Max(float val1, float val2) - { - if (val1 > val2) - { - return val1; - } - else - { - return val2; - } - } #endregion + //TODO Min decimal #region Min - public static byte Min(byte val1, byte val2) - { - if (val1 < val2) - { - return val1; - } - else - { - return val2; - } - } //public static decimal Min(decimal val1, decimal val2) //{ @@ -173,65 +96,6 @@ namespace Cosmos.System.Plugs.System // } //} - public static double Min(double val1, double val2) - { - if (val1 < val2) - { - return val1; - } - else - { - return val2; - } - } - - public static short Min(short val1, short val2) - { - if (val1 < val2) - { - return val1; - } - else - { - return val2; - } - } - - public static int Min(int val1, int val2) - { - if (val1 < val2) - { - return val1; - } - else - { - return val2; - } - } - - public static long Min(long val1, long val2) - { - if (val1 < val2) - { - return val1; - } - else - { - return val2; - } - } - - public static float Min(float val1, float val2) - { - if (val1 < val2) - { - return val1; - } - else - { - return val2; - } - } #endregion #region Pow @@ -261,7 +125,7 @@ namespace Cosmos.System.Plugs.System #region Sin public static double Sin(double a) - { + { // should be using assembler instruction bool signSwitch = false; double result = 0; @@ -283,8 +147,6 @@ namespace Cosmos.System.Plugs.System result = (radians) - (Math.Pow(radians, 3) / Factorial(3)); result += (Math.Pow(radians, 5) / Factorial(5)) - (Math.Pow(radians, 7) / Factorial(7)) + (Math.Pow(radians, 9) / Factorial(9)); - //result *= -1; - /* USE WHEN Modulus Works * int sign = 0; for (int i = 3; i < 19; i += 2) @@ -318,7 +180,7 @@ namespace Cosmos.System.Plugs.System } #endregion - #region Factorial + #region Factorial (only used in Sin(), not plug ) public static int Factorial(int n) { if (n == 0) @@ -329,26 +191,23 @@ namespace Cosmos.System.Plugs.System #endregion #region Ceiling - public static double Ceiling(double a) - { - int returnval = (int)Floor(a); - returnval += 1; - return returnval; - } + public static double Ceiling(double a) + { // should be using assembler for bigger values than int or long max + if (a == Double.NaN || a == Double.NegativeInfinity || a == Double.PositiveInfinity) + return a; + int i = (a - (int)a > 0) ? (int)(a + 1) : (int)a; + return i; + } #endregion #region Floor - public static double Floor(double a) - { - int returnval = (int)a; - - if (a < 0) - { - returnval -= 1; - } - - return returnval; - } + public static double Floor(double a) + { // should be using assembler for bigger values than int or long max + if (a == Double.NaN || a == Double.NegativeInfinity || a == Double.PositiveInfinity) + return a; + int i = (a - (int)a < 0) ? (int)(a - 1) : (int)a; + return i; + } #endregion } } \ No newline at end of file